refactor: decouple arbitration licenses from disputes

This commit is contained in:
Richard Ramos 2019-06-13 18:26:13 -04:00
parent 551c0bc67c
commit dd2acd5540
13 changed files with 227 additions and 249 deletions

View File

@ -1,6 +1,109 @@
/* solium-disable security/no-block-members */
pragma solidity ^0.5.8; pragma solidity ^0.5.8;
interface Arbitrable { import "./License.sol";
function setArbitrationResult(uint _escrowId, bool _releaseFunds, address _arbitrator) external;
function getArbitrator(uint _escrowId) external view returns(address); contract Arbitrable {
} mapping(uint => ArbitrationCase) public arbitrationCases;
struct ArbitrationCase {
bool open;
address openBy;
address arbitrator;
ArbitrationResult result;
string motive;
}
event ArbitratorChanged(address arbitrator);
event ArbitrationCanceled(uint escrowId, uint date);
event ArbitrationRequired(uint escrowId, uint date);
event ArbitrationResolved(uint escrowId, ArbitrationResult result, address arbitrator, uint date);
enum ArbitrationResult {UNSOLVED, BUYER, SELLER}
License public arbitratorLicenses;
constructor(address _arbitratorLicenses) public {
arbitratorLicenses = License(_arbitratorLicenses);
}
// Abstract functions
function solveDispute(uint _escrowId, bool _releaseFunds, address _arbitrator) internal;
function getArbitrator(uint _escrowId) public view returns(address);
/**
* @notice arbitration exists
* @param _escrowId Escrow to verify
* @return bool result
*/
function isDisputed(uint _escrowId) public view returns (bool) {
return arbitrationCases[_escrowId].open || arbitrationCases[_escrowId].result != ArbitrationResult.UNSOLVED;
}
/**
* @notice cancel arbitration
* @param _escrowId Escrow to cancel
*/
function cancelArbitration(uint _escrowId) public {
require(arbitrationCases[_escrowId].openBy == msg.sender, "Arbitration can only be canceled by the opener");
require(arbitrationCases[_escrowId].result == ArbitrationResult.UNSOLVED && arbitrationCases[_escrowId].open,
"Arbitration already solved or not open");
delete arbitrationCases[_escrowId];
emit ArbitrationCanceled(_escrowId, block.timestamp);
}
function openDispute(uint _escrowId, address _openBy, string memory motive) internal {
require(!arbitrationCases[_escrowId].open, "Arbitration already open");
require(arbitrationCases[_escrowId].result == ArbitrationResult.UNSOLVED, "Arbitration already solved");
arbitrationCases[_escrowId] = ArbitrationCase({
open: true,
openBy: _openBy,
arbitrator: address(0),
result: ArbitrationResult.UNSOLVED,
motive: motive
});
emit ArbitrationRequired(_escrowId, block.timestamp);
}
/**
* @notice Set arbitration result in favour of the buyer or seller and transfer funds accordingly
* @param _escrowId Id of the escrow
* @param _result Result of the arbitration
*/
function setArbitrationResult(uint _escrowId, ArbitrationResult _result) public {
require(arbitrationCases[_escrowId].open && arbitrationCases[_escrowId].result == ArbitrationResult.UNSOLVED,
"Case must be open and unsolved");
require(_result != ArbitrationResult.UNSOLVED, "Arbitration does not have result");
require(arbitratorLicenses.isLicenseOwner(msg.sender), "Only arbitrators can invoke this function");
require(getArbitrator(_escrowId) == msg.sender, "Invalid escrow arbitrator");
arbitrationCases[_escrowId].open = false;
arbitrationCases[_escrowId].result = _result;
arbitrationCases[_escrowId].arbitrator = msg.sender;
// TODO: incentive mechanism for opening arbitration process
// if(arbitrationCases[_escrowId].openBy != trx.seller || arbitrationCases[_escrowId].openBy != trx.buyer){
// Consider deducting a fee as reward for whoever opened the arbitration process.
// }
emit ArbitrationResolved(_escrowId, _result, msg.sender, block.timestamp);
if(_result == ArbitrationResult.BUYER){
solveDispute(_escrowId, true, msg.sender);
} else {
solveDispute(_escrowId, false, msg.sender);
}
}
}

View File

@ -1,124 +0,0 @@
/* solium-disable security/no-block-members */
pragma solidity ^0.5.8;
import "../common/Ownable.sol";
import "./Arbitrable.sol";
import "./License.sol";
contract Arbitration is Ownable, License {
mapping(uint => ArbitrationCase) public arbitrationCases;
struct ArbitrationCase {
bool open;
address openBy;
address arbitrator;
ArbitrationResult result;
string motive;
}
event ArbitratorChanged(address arbitrator);
event ArbitrationCanceled(uint escrowId, uint date);
event ArbitrationRequired(uint escrowId, uint date);
event ArbitrationResolved(uint escrowId, ArbitrationResult result, address arbitrator, uint date);
enum ArbitrationResult {UNSOLVED, BUYER, SELLER}
Arbitrable public escrow;
constructor(address payable _tokenAddress, uint256 _price)
License(_tokenAddress, _price)
public {
// Do nothing
}
function setEscrowAddress(address _escrow) public onlyOwner {
escrow = Arbitrable(_escrow);
}
/**
* @notice Determine if address is arbitrator
* @param _addr Address to be verified
* @return result
*/
function isArbitrator(address _addr) public view returns(bool){
return isLicenseOwner(_addr);
}
/**
* @notice arbitration exists
* @param _escrowId Escrow to verify
* @return bool result
*/
function exists(uint _escrowId) public view returns (bool) {
return arbitrationCases[_escrowId].open || arbitrationCases[_escrowId].result != ArbitrationResult.UNSOLVED;
}
/**
* @notice cancel arbitration
* @param _escrowId Escrow to cancel
*/
function cancelArbitration(uint _escrowId) public {
require(arbitrationCases[_escrowId].openBy == msg.sender, "Arbitration can only be canceled by the opener");
require(arbitrationCases[_escrowId].result == ArbitrationResult.UNSOLVED && arbitrationCases[_escrowId].open,
"Arbitration already solved or not open");
delete arbitrationCases[_escrowId];
emit ArbitrationCanceled(_escrowId, block.timestamp);
}
function openCase(uint _escrowId, address _openBy, string memory motive) public {
assert(msg.sender == address(escrow)); // Only the escrow address can open cases
require(!arbitrationCases[_escrowId].open, "Arbitration already open");
require(arbitrationCases[_escrowId].result == ArbitrationResult.UNSOLVED, "Arbitration already solved");
arbitrationCases[_escrowId] = ArbitrationCase({
open: true,
openBy: _openBy,
arbitrator: address(0),
result: ArbitrationResult.UNSOLVED,
motive: motive
});
emit ArbitrationRequired(_escrowId, block.timestamp);
}
/**
* @notice Set arbitration result in favour of the buyer or seller and transfer funds accordingly
* @param _escrowId Id of the escrow
* @param _result Result of the arbitration
*/
function setArbitrationResult(uint _escrowId, ArbitrationResult _result) public {
require(arbitrationCases[_escrowId].open && arbitrationCases[_escrowId].result == ArbitrationResult.UNSOLVED,
"Case must be open and unsolved");
require(_result != ArbitrationResult.UNSOLVED, "Arbitration does not have result");
require(isArbitrator(msg.sender), "Only arbitrators can invoke this function");
require(escrow.getArbitrator(_escrowId) == msg.sender, "Invalid escrow arbitrator");
arbitrationCases[_escrowId].open = false;
arbitrationCases[_escrowId].result = _result;
arbitrationCases[_escrowId].arbitrator = msg.sender;
// TODO: incentive mechanism for opening arbitration process
// if(arbitrationCases[_escrowId].openBy != trx.seller || arbitrationCases[_escrowId].openBy != trx.buyer){
// Consider deducting a fee as reward for whoever opened the arbitration process.
// }
emit ArbitrationResolved(_escrowId, _result, msg.sender, block.timestamp);
if(_result == ArbitrationResult.BUYER){
escrow.setArbitrationResult(_escrowId, true, msg.sender);
} else {
escrow.setArbitrationResult(_escrowId, false, msg.sender);
}
}
}

View File

@ -10,7 +10,6 @@ import "../token/ERC20Token.sol";
import "./License.sol"; import "./License.sol";
import "./MetadataStore.sol"; import "./MetadataStore.sol";
import "./Fees.sol"; import "./Fees.sol";
import "./Arbitration.sol";
import "./Arbitrable.sol"; import "./Arbitrable.sol";
import "tabookey-gasless/contracts/RelayRecipient.sol"; import "tabookey-gasless/contracts/RelayRecipient.sol";
@ -26,14 +25,15 @@ contract Escrow is Pausable, MessageSigned, Fees, Arbitrable, RelayRecipient {
constructor( constructor(
address _license, address _license,
address _arbitration, address _arbitrationLicense,
address _metadataStore, address _metadataStore,
address _feeToken, address _feeToken,
address _feeDestination, address _feeDestination,
uint _feeAmount) uint _feeAmount)
Fees(_feeToken, _feeDestination, _feeAmount) public { Fees(_feeToken, _feeDestination, _feeAmount)
Arbitrable(_arbitrationLicense)
public {
license = License(_license); license = License(_license);
arbitration = Arbitration(_arbitration);
metadataStore = MetadataStore(_metadataStore); metadataStore = MetadataStore(_metadataStore);
} }
@ -41,8 +41,6 @@ contract Escrow is Pausable, MessageSigned, Fees, Arbitrable, RelayRecipient {
set_relay_hub(RelayHub(_relayHub)); set_relay_hub(RelayHub(_relayHub));
} }
Arbitration arbitration;
struct EscrowTransaction { struct EscrowTransaction {
uint256 offerId; uint256 offerId;
uint256 tokenAmount; uint256 tokenAmount;
@ -423,7 +421,7 @@ contract Escrow is Pausable, MessageSigned, Fees, Arbitrable, RelayRecipient {
function rateTransaction(uint _escrowId, uint _rate) external whenNotPaused { function rateTransaction(uint _escrowId, uint _rate) external whenNotPaused {
require(_rate >= 1, "Rating needs to be at least 1"); require(_rate >= 1, "Rating needs to be at least 1");
require(_rate <= 5, "Rating needs to be at less than or equal to 5"); require(_rate <= 5, "Rating needs to be at less than or equal to 5");
require(!arbitration.exists(_escrowId), "Can't rate a transaction that has an arbitration process"); require(!isDisputed(_escrowId), "Can't rate a transaction that has an arbitration process");
EscrowTransaction storage trx = transactions[_escrowId]; EscrowTransaction storage trx = transactions[_escrowId];
@ -445,11 +443,11 @@ contract Escrow is Pausable, MessageSigned, Fees, Arbitrable, RelayRecipient {
function openCase(uint _escrowId, string calldata motive) external { function openCase(uint _escrowId, string calldata motive) external {
EscrowTransaction storage trx = transactions[_escrowId]; EscrowTransaction storage trx = transactions[_escrowId];
require(!arbitration.exists(_escrowId), "Case already exist"); require(!isDisputed(_escrowId), "Case already exist");
require(trx.buyer == get_sender() || metadataStore.getOfferOwner(trx.offerId) == get_sender(), "Only a buyer or seller can open a case"); require(trx.buyer == get_sender() || metadataStore.getOfferOwner(trx.offerId) == get_sender(), "Only a buyer or seller can open a case");
require(trx.status == EscrowStatus.PAID, "Cases can only be open for paid transactions"); require(trx.status == EscrowStatus.PAID, "Cases can only be open for paid transactions");
arbitration.openCase(_escrowId, get_sender(), motive); openDispute(_escrowId, get_sender(), motive);
} }
/** /**
@ -458,19 +456,18 @@ contract Escrow is Pausable, MessageSigned, Fees, Arbitrable, RelayRecipient {
* @param _signature Signed message result of openCaseSignHash(uint256) * @param _signature Signed message result of openCaseSignHash(uint256)
* @dev Consider opening a dispute in aragon court. * @dev Consider opening a dispute in aragon court.
*/ */
function openCaseWithSignature(uint _escrowId, bytes calldata _signature) external { function openCaseWithSignature(uint _escrowId, string calldata motive, bytes calldata _signature) external {
EscrowTransaction storage trx = transactions[_escrowId]; EscrowTransaction storage trx = transactions[_escrowId];
require(!arbitration.exists(_escrowId), "Case already exist"); require(!isDisputed(_escrowId), "Case already exist");
require(trx.status == EscrowStatus.PAID, "Cases can only be open for paid transactions"); require(trx.status == EscrowStatus.PAID, "Cases can only be open for paid transactions");
address senderAddress = recoverAddress(getSignHash(openCaseSignHash(_escrowId)), _signature); address senderAddress = recoverAddress(getSignHash(openCaseSignHash(_escrowId, motive)), _signature);
require(trx.buyer == senderAddress || metadataStore.getOfferOwner(trx.offerId) == senderAddress, require(trx.buyer == senderAddress || metadataStore.getOfferOwner(trx.offerId) == senderAddress,
"Only a buyer or seller can open a case"); "Only a buyer or seller can open a case");
// FIXME get actual motive from the signature if possible openDispute(_escrowId, get_sender(), motive);
arbitration.openCase(_escrowId, get_sender(), '');
} }
/** /**
@ -479,9 +476,7 @@ contract Escrow is Pausable, MessageSigned, Fees, Arbitrable, RelayRecipient {
* @param _releaseFunds Release funds to buyer or cancel escrow * @param _releaseFunds Release funds to buyer or cancel escrow
* @param _arbitrator Arbitrator address * @param _arbitrator Arbitrator address
*/ */
function setArbitrationResult(uint _escrowId, bool _releaseFunds, address _arbitrator) external { function solveDispute(uint _escrowId, bool _releaseFunds, address _arbitrator) internal {
assert(get_sender() == address(arbitration)); // Only arbitration contract can invoke this
EscrowTransaction storage trx = transactions[_escrowId]; EscrowTransaction storage trx = transactions[_escrowId];
address payable seller = metadataStore.getOfferOwner(trx.offerId); address payable seller = metadataStore.getOfferOwner(trx.offerId);
@ -511,12 +506,13 @@ contract Escrow is Pausable, MessageSigned, Fees, Arbitrable, RelayRecipient {
* @return message hash * @return message hash
* @dev Once message is signed, pass it as _signature of openCase(uint256,bytes) * @dev Once message is signed, pass it as _signature of openCase(uint256,bytes)
*/ */
function openCaseSignHash(uint _escrowId) public view returns(bytes32){ function openCaseSignHash(uint _escrowId, string memory motive) public view returns(bytes32){
return keccak256( return keccak256(
abi.encodePacked( abi.encodePacked(
address(this), address(this),
"openCase(uint256)", "openCase(uint256)",
_escrowId _escrowId,
motive
) )
); );
} }

View File

@ -69,25 +69,29 @@ module.exports = {
contracts: { contracts: {
License: { License: {
deploy: false
},
SellerLicense: {
instanceOf: "License",
args: [ args: [
"$SNT", "$SNT",
LICENSE_PRICE LICENSE_PRICE
] ]
}, },
"MetadataStore": { "MetadataStore": {
args: ["$License", "$Arbitration"] args: ["$SellerLicense", "$ArbitrationLicense"]
}, },
Arbitration: { ArbitrationLicense: {
instanceOf: "License",
args: [ args: [
"$SNT", "$SNT",
ARB_LICENSE_PRICE ARB_LICENSE_PRICE
] ]
}, },
Escrow: { Escrow: {
args: ["$License", "$Arbitration", "$MetadataStore", "$SNT", BURN_ADDRESS, FEE_AMOUNT], args: ["$SellerLicense", "$ArbitrationLicense", "$MetadataStore", "$SNT", BURN_ADDRESS, FEE_AMOUNT],
deps: ['RelayHub'], deps: ['RelayHub'],
onDeploy: [ onDeploy: [
"Arbitration.methods.setEscrowAddress('$Escrow').send()",
"MetadataStore.methods.setEscrowAddress('$Escrow').send()", "MetadataStore.methods.setEscrowAddress('$Escrow').send()",
"Escrow.methods.setRelayHubAddress('$RelayHub').send()", "Escrow.methods.setRelayHubAddress('$RelayHub').send()",
"RelayHub.methods.depositFor('$Escrow').send({value: 1000000000000000000})" "RelayHub.methods.depositFor('$Escrow').send({value: 1000000000000000000})"
@ -264,10 +268,9 @@ module.exports = {
tracking: 'shared.ropsten.chains.json', tracking: 'shared.ropsten.chains.json',
contracts: { contracts: {
Escrow: { Escrow: {
args: ["$License", "$Arbitration", "$MetadataStore", "$SNT", BURN_ADDRESS, FEE_AMOUNT], args: ["$SellerLicense", "$ArbitrationLicense", "$MetadataStore", "$SNT", BURN_ADDRESS, FEE_AMOUNT],
deps: ['RelayHub'], deps: ['RelayHub'],
onDeploy: [ onDeploy: [
"Arbitration.methods.setEscrowAddress('$Escrow').send()",
"MetadataStore.methods.setEscrowAddress('$Escrow').send()", "MetadataStore.methods.setEscrowAddress('$Escrow').send()",
"Escrow.methods.setRelayHubAddress('$RelayHub').send()", "Escrow.methods.setRelayHubAddress('$RelayHub').send()",
"RelayHub.methods.depositFor('$Escrow').send({value: 300000000000000000})" "RelayHub.methods.depositFor('$Escrow').send({value: 300000000000000000})"

View File

@ -39,11 +39,8 @@ module.exports = async (licensePrice, arbitrationLicensePrice, feeAmount, deps)
console.log("Buy arbitration license"); console.log("Buy arbitration license");
{ {
console.log(deps.contracts.Arbitration._address); const buyLicense = deps.contracts.ArbitrationLicense.methods.buy().encodeABI();
console.log(arbitrationLicensePrice); const toSend = deps.contracts.SNT.methods.approveAndCall(deps.contracts.ArbitrationLicense._address, arbitrationLicensePrice, buyLicense);
const buyLicense = deps.contracts.Arbitration.methods.buy().encodeABI();
const toSend = deps.contracts.SNT.methods.approveAndCall(deps.contracts.Arbitration._address, arbitrationLicensePrice, buyLicense);
const gas = await toSend.estimateGas({from: arbitrator}); const gas = await toSend.estimateGas({from: arbitrator});
await toSend.send({from: arbitrator, gas}); await toSend.send({from: arbitrator, gas});
@ -51,8 +48,8 @@ module.exports = async (licensePrice, arbitrationLicensePrice, feeAmount, deps)
console.log('Buy Licenses...'); console.log('Buy Licenses...');
await Promise.all(addresses.slice(1, 8).map(async (address) => { await Promise.all(addresses.slice(1, 8).map(async (address) => {
const buyLicense = deps.contracts.License.methods.buy().encodeABI(); const buyLicense = deps.contracts.SellerLicense.methods.buy().encodeABI();
const toSend = deps.contracts.SNT.methods.approveAndCall(deps.contracts.License._address, licensePrice, buyLicense); const toSend = deps.contracts.SNT.methods.approveAndCall(deps.contracts.SellerLicense._address, licensePrice, buyLicense);
const gas = await toSend.estimateGas({from: address}); const gas = await toSend.estimateGas({from: address});
return toSend.send({from: address, gas}); return toSend.send({from: address, gas});
@ -148,7 +145,7 @@ module.exports = async (licensePrice, arbitrationLicensePrice, feeAmount, deps)
const accounts = await Promise.all(addresses.map(async(address) => { const accounts = await Promise.all(addresses.map(async(address) => {
const ethBalance = await deps.web3.eth.getBalance(address); const ethBalance = await deps.web3.eth.getBalance(address);
const sntBalance = await deps.contracts.SNT.methods.balanceOf(address).call(); const sntBalance = await deps.contracts.SNT.methods.balanceOf(address).call();
const isLicenseOwner = await deps.contracts.License.methods.isLicenseOwner(address).call(); const isLicenseOwner = await deps.contracts.SellerLicense.methods.isLicenseOwner(address).call();
let user = {}; let user = {};
let offers = []; let offers = [];
const isUser = await deps.contracts.MetadataStore.methods.userWhitelist(address).call(); const isUser = await deps.contracts.MetadataStore.methods.userWhitelist(address).call();

View File

@ -1,6 +1,5 @@
import {ARBITRATION_UNSOLVED, GET_DISPUTED_ESCROWS, RESOLVE_DISPUTE, RESOLVE_DISPUTE_FAILED, BUY_LICENSE, CHECK_LICENSE_OWNER, LOAD_PRICE, LOAD_ARBITRATION, GET_ARBITRATORS, OPEN_DISPUTE, CANCEL_DISPUTE} from './constants'; import {ARBITRATION_UNSOLVED, GET_DISPUTED_ESCROWS, RESOLVE_DISPUTE, RESOLVE_DISPUTE_FAILED, BUY_LICENSE, CHECK_LICENSE_OWNER, LOAD_PRICE, LOAD_ARBITRATION, GET_ARBITRATORS, OPEN_DISPUTE, CANCEL_DISPUTE} from './constants';
import Escrow from '../../../embarkArtifacts/contracts/Escrow'; import Escrow from '../../../embarkArtifacts/contracts/Escrow';
import Arbitration from '../../../embarkArtifacts/contracts/Arbitration';
export const getDisputedEscrows = () => ({type: GET_DISPUTED_ESCROWS}); export const getDisputedEscrows = () => ({type: GET_DISPUTED_ESCROWS});
@ -15,13 +14,13 @@ export const resolveDispute = (escrowId, result) => {
type: RESOLVE_DISPUTE, type: RESOLVE_DISPUTE,
escrowId, escrowId,
result, result,
toSend: Arbitration.methods.setArbitrationResult(escrowId, result) toSend: Escrow.methods.setArbitrationResult(escrowId, result)
}; };
}; };
export const openDispute = (escrowId, motive) => ({type: OPEN_DISPUTE, escrowId, toSend: Escrow.methods.openCase(escrowId, motive || '')}); export const openDispute = (escrowId, motive) => ({type: OPEN_DISPUTE, escrowId, toSend: Escrow.methods.openCase(escrowId, motive || '')});
export const cancelDispute = (escrowId) => ({type: CANCEL_DISPUTE, escrowId, toSend: Arbitration.methods.cancelArbitration(escrowId)}); export const cancelDispute = (escrowId) => ({type: CANCEL_DISPUTE, escrowId, toSend: Escrow.methods.cancelArbitration(escrowId)});
export const loadArbitration = (escrowId) => { export const loadArbitration = (escrowId) => {
return {type: LOAD_ARBITRATION, escrowId}; return {type: LOAD_ARBITRATION, escrowId};

View File

@ -1,6 +1,6 @@
/* global web3 */ /* global web3 */
import Escrow from '../../../embarkArtifacts/contracts/Escrow'; import Escrow from '../../../embarkArtifacts/contracts/Escrow';
import Arbitration from '../../../embarkArtifacts/contracts/Arbitration'; import ArbitrationLicense from '../../../embarkArtifacts/contracts/ArbitrationLicense';
import SNT from '../../../embarkArtifacts/contracts/SNT'; import SNT from '../../../embarkArtifacts/contracts/SNT';
import MetadataStore from '../../../embarkArtifacts/contracts/MetadataStore'; import MetadataStore from '../../../embarkArtifacts/contracts/MetadataStore';
import moment from 'moment'; import moment from 'moment';
@ -31,10 +31,10 @@ export function *onCancelDispute() {
export function *doGetArbitrators() { export function *doGetArbitrators() {
try { try {
const cnt = yield call(Arbitration.methods.getNumLicenseOwners().call); const cnt = yield call(ArbitrationLicense.methods.getNumLicenseOwners().call);
const arbitrators = []; const arbitrators = [];
for(let i = 0; i < cnt; i++){ for(let i = 0; i < cnt; i++){
arbitrators.push(yield call(Arbitration.methods.licenseOwners(i).call)); arbitrators.push(yield call(ArbitrationLicense.methods.licenseOwners(i).call));
} }
yield put({type: GET_ARBITRATORS_SUCCEEDED, arbitrators}); yield put({type: GET_ARBITRATORS_SUCCEEDED, arbitrators});
} catch (error) { } catch (error) {
@ -45,7 +45,7 @@ export function *doGetArbitrators() {
export function *doGetEscrows() { export function *doGetEscrows() {
try { try {
const events = yield Arbitration.getPastEvents('ArbitrationRequired', {fromBlock: 1}); const events = yield Escrow.getPastEvents('ArbitrationRequired', {fromBlock: 1});
const escrows = []; const escrows = [];
for (let i = 0; i < events.length; i++) { for (let i = 0; i < events.length; i++) {
@ -56,7 +56,7 @@ export function *doGetEscrows() {
escrow.escrowId = escrowId; escrow.escrowId = escrowId;
escrow.seller = offer.owner; escrow.seller = offer.owner;
escrow.arbitration = yield call(Arbitration.methods.arbitrationCases(escrowId).call); escrow.arbitration = yield call(Escrow.methods.arbitrationCases(escrowId).call);
escrow.arbitration.createDate = moment(events[i].returnValues.date * 1000).format("DD.MM.YY"); escrow.arbitration.createDate = moment(events[i].returnValues.date * 1000).format("DD.MM.YY");
escrows.push(escrow); escrows.push(escrow);
@ -88,7 +88,7 @@ export function *doLoadArbitration({escrowId}) {
escrow.escrowId = escrowId; escrow.escrowId = escrowId;
escrow.seller = offer.owner; escrow.seller = offer.owner;
escrow.offer = offer; escrow.offer = offer;
escrow.arbitration = yield call(Arbitration.methods.arbitrationCases(escrowId).call); escrow.arbitration = yield call(Escrow.methods.arbitrationCases(escrowId).call);
yield put({type: LOAD_ARBITRATION_SUCCEEDED, escrow}); yield put({type: LOAD_ARBITRATION_SUCCEEDED, escrow});
} catch (error) { } catch (error) {
@ -104,9 +104,9 @@ export function *onLoadArbitration() {
export function *doBuyLicense() { export function *doBuyLicense() {
try { try {
const price = yield call(Arbitration.methods.price().call); const price = yield call(ArbitrationLicense.methods.price().call);
const encodedCall = Arbitration.methods.buy().encodeABI(); const encodedCall = ArbitrationLicense.methods.buy().encodeABI();
const toSend = SNT.methods.approveAndCall(Arbitration.options.address, price, encodedCall); const toSend = SNT.methods.approveAndCall(ArbitrationLicense.options.address, price, encodedCall);
const estimatedGas = yield call(toSend.estimateGas); const estimatedGas = yield call(toSend.estimateGas);
const promiseEvent = toSend.send({gasLimit: estimatedGas + 2000}); const promiseEvent = toSend.send({gasLimit: estimatedGas + 2000});
const channel = eventChannel(promiseEventEmitter.bind(null, promiseEvent)); const channel = eventChannel(promiseEventEmitter.bind(null, promiseEvent));
@ -134,7 +134,7 @@ export function *onBuyLicense() {
export function *loadPrice() { export function *loadPrice() {
try { try {
const price = yield call(Arbitration.methods.price().call); const price = yield call(ArbitrationLicense.methods.price().call);
yield put({type: LOAD_PRICE_SUCCEEDED, price}); yield put({type: LOAD_PRICE_SUCCEEDED, price});
} catch (error) { } catch (error) {
console.error(error); console.error(error);
@ -148,7 +148,7 @@ export function *onLoadPrice() {
export function *doCheckLicenseOwner() { export function *doCheckLicenseOwner() {
try { try {
const isLicenseOwner = yield call(Arbitration.methods.isLicenseOwner(web3.eth.defaultAccount).call); const isLicenseOwner = yield call(ArbitrationLicense.methods.isLicenseOwner(web3.eth.defaultAccount).call);
yield put({type: CHECK_LICENSE_OWNER_SUCCEEDED, isLicenseOwner}); yield put({type: CHECK_LICENSE_OWNER_SUCCEEDED, isLicenseOwner});
} catch (error) { } catch (error) {
console.error(error); console.error(error);

View File

@ -1,5 +1,5 @@
/*global web3*/ /*global web3*/
import License from '../../../embarkArtifacts/contracts/License'; import SellerLicense from '../../../embarkArtifacts/contracts/SellerLicense';
import SNT from '../../../embarkArtifacts/contracts/SNT'; import SNT from '../../../embarkArtifacts/contracts/SNT';
import {fork, takeEvery, call, put, take} from 'redux-saga/effects'; import {fork, takeEvery, call, put, take} from 'redux-saga/effects';
import { import {
@ -18,9 +18,9 @@ window.SNT = SNT;
export function *doBuyLicense() { export function *doBuyLicense() {
try { try {
const price = yield call(License.methods.price().call); const price = yield call(SellerLicense.methods.price().call);
const encodedCall = License.methods.buy().encodeABI(); const encodedCall = SellerLicense.methods.buy().encodeABI();
const toSend = SNT.methods.approveAndCall(License.options.address, price, encodedCall); const toSend = SNT.methods.approveAndCall(SellerLicense.options.address, price, encodedCall);
const estimatedGas = yield call(toSend.estimateGas); const estimatedGas = yield call(toSend.estimateGas);
const promiseEvent = toSend.send({gasLimit: estimatedGas + 2000}); const promiseEvent = toSend.send({gasLimit: estimatedGas + 2000});
const channel = eventChannel(promiseEventEmitter.bind(null, promiseEvent)); const channel = eventChannel(promiseEventEmitter.bind(null, promiseEvent));
@ -48,7 +48,7 @@ export function *onBuyLicense() {
export function *loadPrice() { export function *loadPrice() {
try { try {
const price = yield call(License.methods.price().call); const price = yield call(SellerLicense.methods.price().call);
yield put({type: LOAD_PRICE_SUCCEEDED, price}); yield put({type: LOAD_PRICE_SUCCEEDED, price});
} catch (error) { } catch (error) {
console.error(error); console.error(error);
@ -62,7 +62,7 @@ export function *onLoadPrice() {
export function *doCheckLicenseOwner() { export function *doCheckLicenseOwner() {
try { try {
const isLicenseOwner = yield call(License.methods.isLicenseOwner(web3.eth.defaultAccount).call); const isLicenseOwner = yield call(SellerLicense.methods.isLicenseOwner(web3.eth.defaultAccount).call);
yield put({type: CHECK_LICENSE_OWNER_SUCCEEDED, isLicenseOwner}); yield put({type: CHECK_LICENSE_OWNER_SUCCEEDED, isLicenseOwner});
} catch (error) { } catch (error) {
console.error(error); console.error(error);
@ -77,7 +77,7 @@ export function *onCheckLicenseOwner() {
export function *doGetLicenseOwners() { export function *doGetLicenseOwners() {
try { try {
// TODO get more information like position and rate // TODO get more information like position and rate
const events = yield License.getPastEvents('Bought', {fromBlock: 1}); const events = yield SellerLicense.getPastEvents('Bought', {fromBlock: 1});
const licenseOwners = events.map(event => { const licenseOwners = events.map(event => {
return {address: event.returnValues.buyer}; return {address: event.returnValues.buyer};
}); });

View File

@ -1,5 +1,5 @@
import MetadataStore from '../../../embarkArtifacts/contracts/MetadataStore'; import MetadataStore from '../../../embarkArtifacts/contracts/MetadataStore';
import Arbitration from '../../../embarkArtifacts/contracts/Arbitration'; import ArbitrationLicense from '../../../embarkArtifacts/contracts/ArbitrationLicense';
import Escrow from '../../../embarkArtifacts/contracts/Escrow'; import Escrow from '../../../embarkArtifacts/contracts/Escrow';
import {fork, takeEvery, put, all} from 'redux-saga/effects'; import {fork, takeEvery, put, all} from 'redux-saga/effects';
@ -16,7 +16,7 @@ import {getLocation} from '../../services/googleMap';
export function *loadUser({address}) { export function *loadUser({address}) {
try { try {
const isArbitrator = yield Arbitration.methods.isArbitrator(address).call(); const isArbitrator = yield ArbitrationLicense.methods.isLicenseOwner(address).call();
const isUser = yield MetadataStore.methods.userWhitelist(address).call(); const isUser = yield MetadataStore.methods.userWhitelist(address).call();
let user = { let user = {

View File

@ -78,9 +78,6 @@ class EditMyContact extends Component {
} }
render() { render() {
console.log(this.props);
console.log(this.state);
if(!this.props.profile){ if(!this.props.profile){
return <Loading />; return <Loading />;
} }

View File

@ -2,12 +2,12 @@
const EthUtil = require('ethereumjs-util'); const EthUtil = require('ethereumjs-util');
const TestUtils = require("../utils/testUtils"); const TestUtils = require("../utils/testUtils");
const License = embark.require('Embark/contracts/License'); const SellerLicense = embark.require('Embark/contracts/SellerLicense');
const ArbitrationLicense = embark.require('Embark/contracts/ArbitrationLicense');
const MetadataStore = embark.require('Embark/contracts/MetadataStore'); const MetadataStore = embark.require('Embark/contracts/MetadataStore');
const Escrow = embark.require('Embark/contracts/Escrow'); const Escrow = embark.require('Embark/contracts/Escrow');
const StandardToken = embark.require('Embark/contracts/StandardToken'); const StandardToken = embark.require('Embark/contracts/StandardToken');
const SNT = embark.require('Embark/contracts/SNT'); const SNT = embark.require('Embark/contracts/SNT');
const Arbitration = embark.require('Embark/contracts/Arbitration');
const ESCROW_CREATED = 0; const ESCROW_CREATED = 0;
@ -54,20 +54,22 @@ config({
] ]
}, },
License: { License: {
deploy: false
},
SellerLicense: {
instanceOf: "License",
args: ["$SNT", 10]
},
ArbitrationLicense: {
instanceOf: "License",
args: ["$SNT", 10] args: ["$SNT", 10]
}, },
MetadataStore: { MetadataStore: {
args: ["$License", "$Arbitration"] args: ["$SellerLicense", "$ArbitrationLicense"]
},
Arbitration: {
args: ["$SNT", 10]
}, },
Escrow: { Escrow: {
args: ["$License", "$Arbitration", "$MetadataStore", "$SNT", "0x0000000000000000000000000000000000000001", feeAmount], args: ["$SellerLicense", "$ArbitrationLicense", "$MetadataStore", "$SNT", "0x0000000000000000000000000000000000000001", feeAmount],
onDeploy: [ onDeploy: ["MetadataStore.methods.setEscrowAddress('$Escrow').send()"]
"Arbitration.methods.setEscrowAddress('$Escrow').send()",
"MetadataStore.methods.setEscrowAddress('$Escrow').send()"
]
}, },
StandardToken: { StandardToken: {
} }
@ -95,27 +97,21 @@ contract("Escrow", function() {
this.timeout(0); this.timeout(0);
before(async () => { before(async () => {
const escrowEvents = Escrow.options.jsonInterface.filter(x => x.type === 'event');
const arbitrationEvents = Arbitration.options.jsonInterface.filter(x => x.type === 'event');
Escrow.options.jsonInterface = Escrow.options.jsonInterface.concat(arbitrationEvents);
Arbitration.options.jsonInterface = Arbitration.options.jsonInterface.concat(escrowEvents);
await SNT.methods.generateTokens(accounts[0], 1000).send(); await SNT.methods.generateTokens(accounts[0], 1000).send();
const encodedCall = License.methods.buy().encodeABI(); const encodedCall = SellerLicense.methods.buy().encodeABI();
await SNT.methods.approveAndCall(License.options.address, 10, encodedCall).send({from: accounts[0]}); await SNT.methods.approveAndCall(SellerLicense.options.address, 10, encodedCall).send({from: accounts[0]});
// Register arbitrators // Register arbitrators
await SNT.methods.generateTokens(arbitrator, 1000).send(); await SNT.methods.generateTokens(arbitrator, 1000).send();
await SNT.methods.generateTokens(arbitrator2, 1000).send(); await SNT.methods.generateTokens(arbitrator2, 1000).send();
const encodedCall2 = Arbitration.methods.buy().encodeABI();
await SNT.methods.approveAndCall(Arbitration.options.address, 10, encodedCall2).send({from: arbitrator});
await SNT.methods.approveAndCall(Arbitration.options.address, 10, encodedCall2).send({from: arbitrator2});
receipt = await MetadataStore.methods.addOffer(TestUtils.zeroAddress, License.address, "London", "USD", "Iuri", [0], 1, arbitrator).send({from: accounts[0]}); const encodedCall2 = ArbitrationLicense.methods.buy().encodeABI();
await SNT.methods.approveAndCall(ArbitrationLicense.options.address, 10, encodedCall2).send({from: arbitrator});
await SNT.methods.approveAndCall(ArbitrationLicense.options.address, 10, encodedCall2).send({from: arbitrator2});
receipt = await MetadataStore.methods.addOffer(TestUtils.zeroAddress, SellerLicense.address, "London", "USD", "Iuri", [0], 1, arbitrator).send({from: accounts[0]});
ethOfferId = receipt.events.OfferAdded.returnValues.offerId; ethOfferId = receipt.events.OfferAdded.returnValues.offerId;
receipt = await MetadataStore.methods.addOffer(StandardToken.options.address, License.address, "London", "USD", "Iuri", [0], 1, arbitrator).send({from: accounts[0]}); receipt = await MetadataStore.methods.addOffer(StandardToken.options.address, SellerLicense.address, "London", "USD", "Iuri", [0], 1, arbitrator).send({from: accounts[0]});
tokenOfferId = receipt.events.OfferAdded.returnValues.offerId; tokenOfferId = receipt.events.OfferAdded.returnValues.offerId;
}); });
@ -676,12 +672,12 @@ contract("Escrow", function() {
receipt = await Escrow.methods['pay(uint256,bytes)'](escrowId, signatureRPC).send({from: accounts[8]}); receipt = await Escrow.methods['pay(uint256,bytes)'](escrowId, signatureRPC).send({from: accounts[8]});
messageToSign = await Escrow.methods.openCaseSignHash(escrowId).call(); messageToSign = await Escrow.methods.openCaseSignHash(escrowId, "My motive is...").call();
msgHash = EthUtil.hashPersonalMessage(Buffer.from(EthUtil.stripHexPrefix(messageToSign), 'hex')); msgHash = EthUtil.hashPersonalMessage(Buffer.from(EthUtil.stripHexPrefix(messageToSign), 'hex'));
signature = EthUtil.ecsign(msgHash, privateKey); signature = EthUtil.ecsign(msgHash, privateKey);
signatureRPC = EthUtil.toRpcSig(signature.v, signature.r, signature.s); signatureRPC = EthUtil.toRpcSig(signature.v, signature.r, signature.s);
receipt = await Escrow.methods.openCaseWithSignature(escrowId, signatureRPC).send({from: accounts[9]}); receipt = await Escrow.methods.openCaseWithSignature(escrowId, "My motive is...", signatureRPC).send({from: accounts[9]});
const arbitrationRequired = receipt.events.ArbitrationRequired; const arbitrationRequired = receipt.events.ArbitrationRequired;
assert(!!arbitrationRequired, "ArbitrationRequired() not triggered"); assert(!!arbitrationRequired, "ArbitrationRequired() not triggered");
assert.equal(arbitrationRequired.returnValues.escrowId, escrowId, "Invalid escrowId"); assert.equal(arbitrationRequired.returnValues.escrowId, escrowId, "Invalid escrowId");
@ -695,7 +691,7 @@ contract("Escrow", function() {
await Escrow.methods.openCase(escrowId, 'Motive').send({from: accounts[1]}); await Escrow.methods.openCase(escrowId, 'Motive').send({from: accounts[1]});
try { try {
receipt = await Arbitration.methods.setArbitrationResult(escrowId, ARBITRATION_SOLVED_BUYER).send({from: accounts[1]}); receipt = await Escrow.methods.setArbitrationResult(escrowId, ARBITRATION_SOLVED_BUYER).send({from: accounts[1]});
assert.fail('should have reverted before'); assert.fail('should have reverted before');
} catch (error) { } catch (error) {
assert.strictEqual(error.message, "VM Exception while processing transaction: revert Only arbitrators can invoke this function"); assert.strictEqual(error.message, "VM Exception while processing transaction: revert Only arbitrators can invoke this function");
@ -707,7 +703,7 @@ contract("Escrow", function() {
await Escrow.methods.openCase(escrowId, 'Motive').send({from: accounts[1]}); await Escrow.methods.openCase(escrowId, 'Motive').send({from: accounts[1]});
try { try {
receipt = await Arbitration.methods.setArbitrationResult(escrowId, ARBITRATION_SOLVED_BUYER).send({from: arbitrator2}); receipt = await Escrow.methods.setArbitrationResult(escrowId, ARBITRATION_SOLVED_BUYER).send({from: arbitrator2});
assert.fail('should have reverted before'); assert.fail('should have reverted before');
} catch (error) { } catch (error) {
TestUtils.assertJump(error); TestUtils.assertJump(error);
@ -719,13 +715,13 @@ contract("Escrow", function() {
receipt = await Escrow.methods.openCase(escrowId, 'Motive').send({from: accounts[1]}); receipt = await Escrow.methods.openCase(escrowId, 'Motive').send({from: accounts[1]});
try { try {
receipt = await Arbitration.methods.cancelArbitration(escrowId).send({from: accounts[0]}); receipt = await Escrow.methods.cancelArbitration(escrowId).send({from: accounts[0]});
assert.fail('should have reverted before'); assert.fail('should have reverted before');
} catch (error) { } catch (error) {
assert.strictEqual(error.message, "VM Exception while processing transaction: revert Arbitration can only be canceled by the opener"); assert.strictEqual(error.message, "VM Exception while processing transaction: revert Arbitration can only be canceled by the opener");
} }
receipt = await Arbitration.methods.cancelArbitration(escrowId).send({from: accounts[1]}); receipt = await Escrow.methods.cancelArbitration(escrowId).send({from: accounts[1]});
const arbitrationCanceled = receipt.events.ArbitrationCanceled; const arbitrationCanceled = receipt.events.ArbitrationCanceled;
assert(!!arbitrationCanceled, "ArbitrationCanceled() not triggered"); assert(!!arbitrationCanceled, "ArbitrationCanceled() not triggered");
assert.equal(arbitrationCanceled.returnValues.escrowId, escrowId, "Invalid escrowId"); assert.equal(arbitrationCanceled.returnValues.escrowId, escrowId, "Invalid escrowId");
@ -735,7 +731,7 @@ contract("Escrow", function() {
await Escrow.methods.pay(escrowId).send({from: accounts[1]}); await Escrow.methods.pay(escrowId).send({from: accounts[1]});
await Escrow.methods.openCase(escrowId, 'Motive').send({from: accounts[1]}); await Escrow.methods.openCase(escrowId, 'Motive').send({from: accounts[1]});
receipt = await Arbitration.methods.setArbitrationResult(escrowId, ARBITRATION_SOLVED_BUYER).send({from: arbitrator}); receipt = await Escrow.methods.setArbitrationResult(escrowId, ARBITRATION_SOLVED_BUYER).send({from: arbitrator});
const released = receipt.events.Released; const released = receipt.events.Released;
assert(!!released, "Released() not triggered"); assert(!!released, "Released() not triggered");
}); });
@ -744,7 +740,7 @@ contract("Escrow", function() {
await Escrow.methods.pay(escrowId).send({from: accounts[1]}); await Escrow.methods.pay(escrowId).send({from: accounts[1]});
await Escrow.methods.openCase(escrowId, 'Motive').send({from: accounts[1]}); await Escrow.methods.openCase(escrowId, 'Motive').send({from: accounts[1]});
receipt = await Arbitration.methods.setArbitrationResult(escrowId, ARBITRATION_SOLVED_SELLER).send({from: arbitrator}); receipt = await Escrow.methods.setArbitrationResult(escrowId, ARBITRATION_SOLVED_SELLER).send({from: arbitrator});
const released = receipt.events.Canceled; const released = receipt.events.Canceled;
assert(!!released, "Canceled() not triggered"); assert(!!released, "Canceled() not triggered");
@ -753,10 +749,10 @@ contract("Escrow", function() {
it("cannot cancel a solved arbitration", async() => { it("cannot cancel a solved arbitration", async() => {
await Escrow.methods.pay(escrowId).send({from: accounts[1]}); await Escrow.methods.pay(escrowId).send({from: accounts[1]});
receipt = await Escrow.methods.openCase(escrowId, 'Motive').send({from: accounts[1]}); receipt = await Escrow.methods.openCase(escrowId, 'Motive').send({from: accounts[1]});
receipt = await Arbitration.methods.setArbitrationResult(escrowId, ARBITRATION_SOLVED_SELLER).send({from: arbitrator}); receipt = await Escrow.methods.setArbitrationResult(escrowId, ARBITRATION_SOLVED_SELLER).send({from: arbitrator});
try { try {
receipt = await Arbitration.methods.cancelArbitration(escrowId).send({from: accounts[1]}); receipt = await Escrow.methods.cancelArbitration(escrowId).send({from: accounts[1]});
assert.fail('should have reverted before'); assert.fail('should have reverted before');
} catch (error) { } catch (error) {
assert.strictEqual(error.message, "VM Exception while processing transaction: revert Arbitration already solved or not open"); assert.strictEqual(error.message, "VM Exception while processing transaction: revert Arbitration already solved or not open");
@ -868,10 +864,10 @@ contract("Escrow", function() {
}); });
it("arbitrator should be valid", async () => { it("arbitrator should be valid", async () => {
const isArbitrator = await Arbitration.methods.isArbitrator(arbitrator).call(); const isArbitrator = await ArbitrationLicense.methods.isLicenseOwner(arbitrator).call();
assert.equal(isArbitrator, true, "Invalid arbitrator"); assert.equal(isArbitrator, true, "Invalid arbitrator");
const nonArbitrator = await Arbitration.methods.isArbitrator(accounts[5]).call(); const nonArbitrator = await ArbitrationLicense.methods.isLicenseOwner(accounts[5]).call();
assert.equal(nonArbitrator, false, "Account should not be an arbitrator"); assert.equal(nonArbitrator, false, "Account should not be an arbitrator");
}); });
}); });

View File

@ -1,9 +1,9 @@
/*global contract, config, it, embark, web3, before, describe, beforeEach*/ /*global contract, config, it, embark, web3, before, describe, beforeEach*/
const TestUtils = require("../utils/testUtils"); const TestUtils = require("../utils/testUtils");
const License = embark.require('Embark/contracts/License'); const SellerLicense = embark.require('Embark/contracts/SellerLicense');
const MetadataStore = embark.require('Embark/contracts/MetadataStore'); const MetadataStore = embark.require('Embark/contracts/MetadataStore');
const Arbitration = embark.require('Embark/contracts/Arbitration'); const ArbitrationLicense = embark.require('Embark/contracts/ArbitrationLicense');
const Escrow = embark.require('Embark/contracts/Escrow'); const Escrow = embark.require('Embark/contracts/Escrow');
const StandardToken = embark.require('Embark/contracts/StandardToken'); const StandardToken = embark.require('Embark/contracts/StandardToken');
const SNT = embark.require('Embark/contracts/SNT'); const SNT = embark.require('Embark/contracts/SNT');
@ -36,18 +36,22 @@ config({
] ]
}, },
License: { License: {
deploy: false
},
SellerLicense: {
instanceOf: "License",
args: ["$SNT", 10] args: ["$SNT", 10]
}, },
MetadataStore: { MetadataStore: {
args: ["$License", "$Arbitration"] args: ["$SellerLicense", "$ArbitrationLicense"]
}, },
Arbitration: { ArbitrationLicense: {
instanceOf: "License",
args: ["$SNT", 10] args: ["$SNT", 10]
}, },
Escrow: { Escrow: {
args: ["$License", "$accounts[5]", "$MetadataStore", "$SNT", "0x0000000000000000000000000000000000000001", feeAmount], args: ["$SellerLicense", "$ArbitrationLicense", "$MetadataStore", "$SNT", "0x0000000000000000000000000000000000000001", feeAmount],
onDeploy: [ onDeploy: [
"Arbitration.methods.setEscrowAddress('$Escrow').send()",
"MetadataStore.methods.setEscrowAddress('$Escrow').send()" "MetadataStore.methods.setEscrowAddress('$Escrow').send()"
] ]
}, },
@ -75,22 +79,22 @@ contract("Escrow Funding", function() {
before(async () => { before(async () => {
await StandardToken.methods.mint(accounts[0], 100000000).send(); await StandardToken.methods.mint(accounts[0], 100000000).send();
await SNT.methods.generateTokens(accounts[0], 100000000).send(); await SNT.methods.generateTokens(accounts[0], 100000000).send();
const encodedCall = License.methods.buy().encodeABI(); const encodedCall = SellerLicense.methods.buy().encodeABI();
await SNT.methods.approveAndCall(License.options.address, 10, encodedCall).send({from: accounts[0]}); await SNT.methods.approveAndCall(SellerLicense.options.address, 10, encodedCall).send({from: accounts[0]});
// Register arbitrators // Register arbitrators
arbitrator = accounts[9]; arbitrator = accounts[9];
await SNT.methods.generateTokens(arbitrator, 1000).send(); await SNT.methods.generateTokens(arbitrator, 1000).send();
const encodedCall2 = Arbitration.methods.buy().encodeABI(); const encodedCall2 = ArbitrationLicense.methods.buy().encodeABI();
await SNT.methods.approveAndCall(Arbitration.options.address, 10, encodedCall2).send({from: arbitrator}); await SNT.methods.approveAndCall(ArbitrationLicense.options.address, 10, encodedCall2).send({from: arbitrator});
receipt = await MetadataStore.methods.addOffer(TestUtils.zeroAddress, License.address, "London", "USD", "Iuri", [0], 1, arbitrator).send({from: accounts[0]}); receipt = await MetadataStore.methods.addOffer(TestUtils.zeroAddress, SellerLicense.address, "London", "USD", "Iuri", [0], 1, arbitrator).send({from: accounts[0]});
ethOfferId = receipt.events.OfferAdded.returnValues.offerId; ethOfferId = receipt.events.OfferAdded.returnValues.offerId;
receipt = await MetadataStore.methods.addOffer(StandardToken.options.address, License.address, "London", "USD", "Iuri", [0], 1, arbitrator).send({from: accounts[0]}); receipt = await MetadataStore.methods.addOffer(StandardToken.options.address, SellerLicense.address, "London", "USD", "Iuri", [0], 1, arbitrator).send({from: accounts[0]});
tokenOfferId = receipt.events.OfferAdded.returnValues.offerId; tokenOfferId = receipt.events.OfferAdded.returnValues.offerId;
receipt = await MetadataStore.methods.addOffer(SNT.options.address, License.address, "London", "USD", "Iuri", [0], 1, arbitrator).send({from: accounts[0]}); receipt = await MetadataStore.methods.addOffer(SNT.options.address, SellerLicense.address, "London", "USD", "Iuri", [0], 1, arbitrator).send({from: accounts[0]});
SNTOfferId = receipt.events.OfferAdded.returnValues.offerId; SNTOfferId = receipt.events.OfferAdded.returnValues.offerId;
}); });

View File

@ -1,6 +1,8 @@
/*global contract, config, it, assert, before*/ /*global contract, config, it, assert, before*/
const License = require('Embark/contracts/License'); const SellerLicense = require('Embark/contracts/SellerLicense');
const ArbitrationLicense = require('Embark/contracts/ArbitrationLicense');
const SNT = require('Embark/contracts/SNT'); const SNT = require('Embark/contracts/SNT');
const MetadataStore = require('Embark/contracts/MetadataStore'); const MetadataStore = require('Embark/contracts/MetadataStore');
@ -24,14 +26,19 @@ config({
true true
] ]
}, },
Arbitration: { License: {
deploy: false
},
SellerLicense: {
instanceOf: "License",
args: ["$SNT", 10] args: ["$SNT", 10]
}, },
License: { ArbitrationLicense: {
instanceOf: "License",
args: ["$SNT", 10] args: ["$SNT", 10]
}, },
MetadataStore: { MetadataStore: {
args: ["$License", "$Arbitration"] args: ["$SellerLicense", "$ArbitrationLicense"]
} }
} }
}, (_err, web3_accounts) => { }, (_err, web3_accounts) => {
@ -45,7 +52,7 @@ contract("MetadataStore", function () {
it("should not allow to add new user when not license owner", async function () { it("should not allow to add new user when not license owner", async function () {
try { try {
await MetadataStore.methods.addOffer(SNT.address, License.address, "London", "USD", "Iuri", [0], 1, accounts[9]).send(); await MetadataStore.methods.addOffer(SNT.address, SellerLicense.address, "London", "USD", "Iuri", [0], 1, accounts[9]).send();
} catch(error) { } catch(error) {
const usersSize = await MetadataStore.methods.usersSize().call(); const usersSize = await MetadataStore.methods.usersSize().call();
assert.strictEqual(usersSize, '0'); assert.strictEqual(usersSize, '0');
@ -53,9 +60,9 @@ contract("MetadataStore", function () {
}); });
it("should allow to add new user and offer when license owner", async function () { it("should allow to add new user and offer when license owner", async function () {
const encodedCall = License.methods.buy().encodeABI(); const encodedCall = SellerLicense.methods.buy().encodeABI();
await SNT.methods.approveAndCall(License.options.address, 10, encodedCall).send(); await SNT.methods.approveAndCall(SellerLicense.options.address, 10, encodedCall).send();
await MetadataStore.methods.addOffer(SNT.address, License.address, "London", "USD", "Iuri", [0], 1, accounts[9]).send(); await MetadataStore.methods.addOffer(SNT.address, SellerLicense.address, "London", "USD", "Iuri", [0], 1, accounts[9]).send();
const usersSize = await MetadataStore.methods.usersSize().call(); const usersSize = await MetadataStore.methods.usersSize().call();
assert.strictEqual(usersSize, '1'); assert.strictEqual(usersSize, '1');
const offersSize = await MetadataStore.methods.offersSize().call(); const offersSize = await MetadataStore.methods.offersSize().call();
@ -63,7 +70,7 @@ contract("MetadataStore", function () {
}); });
it("should allow to add new offer only when already a user", async function () { it("should allow to add new offer only when already a user", async function () {
await MetadataStore.methods.addOffer(SNT.address, License.address, "London", "EUR", "Iuri", [0], 1, accounts[9]).send(); await MetadataStore.methods.addOffer(SNT.address, SellerLicense.address, "London", "EUR", "Iuri", [0], 1, accounts[9]).send();
const usersSize = await MetadataStore.methods.usersSize().call(); const usersSize = await MetadataStore.methods.usersSize().call();
assert.strictEqual(usersSize, '1'); assert.strictEqual(usersSize, '1');
const offersSize = await MetadataStore.methods.offersSize().call(); const offersSize = await MetadataStore.methods.offersSize().call();
@ -72,7 +79,7 @@ contract("MetadataStore", function () {
it("should not allow to add new offer when margin is more than 100", async function () { it("should not allow to add new offer when margin is more than 100", async function () {
try { try {
await MetadataStore.methods.addOffer(SNT.address, License.address, "London", "USD", "Iuri", [0], 101, accounts[9]).send(); await MetadataStore.methods.addOffer(SNT.address, SellerLicense.address, "London", "USD", "Iuri", [0], 101, accounts[9]).send();
} catch(error) { } catch(error) {
const usersSize = await MetadataStore.methods.usersSize().call(); const usersSize = await MetadataStore.methods.usersSize().call();
assert.strictEqual(usersSize, '1'); assert.strictEqual(usersSize, '1');
@ -80,7 +87,7 @@ contract("MetadataStore", function () {
}); });
it("should allow to update a user and offer", async function () { it("should allow to update a user and offer", async function () {
await MetadataStore.methods.updateOffer(0, SNT.address, License.address, "Paris", "EUR", "Iuri", [0], 1, accounts[9]).send(); await MetadataStore.methods.updateOffer(0, SNT.address, SellerLicense.address, "Paris", "EUR", "Iuri", [0], 1, accounts[9]).send();
const usersSize = await MetadataStore.methods.usersSize().call(); const usersSize = await MetadataStore.methods.usersSize().call();
assert.strictEqual(usersSize, '1'); assert.strictEqual(usersSize, '1');
const user = await MetadataStore.methods.users(0).call(); const user = await MetadataStore.methods.users(0).call();
@ -100,7 +107,7 @@ contract("MetadataStore", function () {
}); });
it("should allow to delete an offer", async function () { it("should allow to delete an offer", async function () {
const receipt = await MetadataStore.methods.addOffer(SNT.address, License.address, "London", "EUR", "Iuri", [0], 1, accounts[9]).send(); const receipt = await MetadataStore.methods.addOffer(SNT.address, SellerLicense.address, "London", "EUR", "Iuri", [0], 1, accounts[9]).send();
const offerAdded = receipt.events.OfferAdded; const offerAdded = receipt.events.OfferAdded;
const offerId = offerAdded.returnValues.offerId; const offerId = offerAdded.returnValues.offerId;