Apply comments enhancements

This commit is contained in:
Roman Storm 2018-03-11 12:37:37 -07:00
parent cb33ddbb3b
commit 54e34c578d
16 changed files with 632 additions and 230 deletions

View File

@ -51,4 +51,8 @@ contract BridgeValidators is Ownable, IBridgeValidators {
function requiredSignatures() public view returns(uint8) {
return requiredValidators;
}
function currentOwner() public view returns(address) {
return owner;
}
}

View File

@ -5,6 +5,6 @@ import "zeppelin-solidity/contracts/token/ERC20/ERC20.sol";
contract ERC677 is ERC20 {
event Transfer(address indexed from, address indexed to, uint value, bytes data);
function transferAndCall(address, uint, bytes) returns (bool);
function transferAndCall(address, uint, bytes) public returns (bool);
}

View File

@ -1,7 +1,6 @@
pragma solidity 0.4.19;
import "./libraries/Helpers.sol";
import "./libraries/Message.sol";
import "./libraries/MessageSigning.sol";
import "./IBridgeValidators.sol";
import "./Validatable.sol";
import "./BridgeDeploymentAddressStorage.sol";
@ -15,12 +14,9 @@ contract ForeignBridge is ERC677Receiver, Validatable, BridgeDeploymentAddressSt
mapping (bytes32 => bytes) messages;
mapping (bytes32 => bytes) signatures;
mapping (bytes32 => bool) messages_signed;
mapping (bytes32 => uint) num_messages_signed;
mapping (bytes32 => uint256) num_messages_signed;
mapping (bytes32 => bool) deposits_signed;
mapping (bytes32 => uint) num_deposits_signed;
mapping (bytes32 => bool) tokenAddressApprovalSigns;
mapping (address => uint256) public numTokenAddressApprovalSigns;
mapping (bytes32 => uint256) num_deposits_signed;
IBurnableMintableERC677Token public erc677token;
@ -33,8 +29,6 @@ contract ForeignBridge is ERC677Receiver, Validatable, BridgeDeploymentAddressSt
/// Collected signatures which should be relayed to home chain.
event CollectedSignatures(address authorityResponsibleForRelay, bytes32 messageHash);
event TokenAddress(address token);
event GasConsumptionLimitsUpdated(uint256 gasLimitDepositRelay, uint256 gasLimitWithdrawConfirm);
event SignedForDeposit(address indexed signer, bytes32 message);
@ -47,13 +41,13 @@ contract ForeignBridge is ERC677Receiver, Validatable, BridgeDeploymentAddressSt
erc677token = IBurnableMintableERC677Token(_erc677token);
}
function setGasLimitDepositRelay(uint256 gas) onlyValidator {
gasLimitDepositRelay = gas;
function setGasLimitDepositRelay(uint256 _gas) public onlyOwner {
gasLimitDepositRelay = _gas;
GasConsumptionLimitsUpdated(gasLimitDepositRelay, gasLimitWithdrawConfirm);
}
function setGasLimitWithdrawConfirm(uint256 gas) onlyValidator {
function setGasLimitWithdrawConfirm(uint256 gas) public onlyOwner {
gasLimitWithdrawConfirm = gas;
GasConsumptionLimitsUpdated(gasLimitDepositRelay, gasLimitWithdrawConfirm);
@ -70,16 +64,18 @@ contract ForeignBridge is ERC677Receiver, Validatable, BridgeDeploymentAddressSt
require(!deposits_signed[hash_sender]);
deposits_signed[hash_sender] = true;
uint signed = num_deposits_signed[hash_msg] + 1;
uint256 signed = num_deposits_signed[hash_msg] + 1;
num_deposits_signed[hash_msg] = signed;
SignedForDeposit(msg.sender, transactionHash);
if (signed == validatorContract.requiredSignatures()) {
// If the bridge contract does not own enough tokens to transfer
// it will couse funds lock on the home side of the bridge
erc677token.mint(recipient, value);
Deposit(recipient, value);
}
SignedForDeposit(msg.sender, transactionHash);
}
function onTokenTransfer(address _from, uint256 _value, bytes _data) external returns(bool) {
@ -125,10 +121,10 @@ contract ForeignBridge is ERC677Receiver, Validatable, BridgeDeploymentAddressSt
num_messages_signed[hash_sender] = signed;
// TODO: this may cause troubles if requiredSignatures len is changed
SignedForWithdraw(msg.sender, hash);
if (signed == validatorContract.requiredSignatures()) {
CollectedSignatures(msg.sender, hash);
}
SignedForWithdraw(msg.sender, hash);
}
function signature(bytes32 hash, uint index) public view returns (bytes) {

View File

@ -1,7 +1,7 @@
pragma solidity ^0.4.19;
import "./libraries/SafeMath.sol";
import "./libraries/Helpers.sol";
import "./libraries/Message.sol";
import "./libraries/MessageSigning.sol";
import "./IBridgeValidators.sol";
import "./Validatable.sol";
import "./BridgeDeploymentAddressStorage.sol";
@ -27,11 +27,12 @@ contract HomeBridge is Validatable, BridgeDeploymentAddressStorage {
Deposit(msg.sender, msg.value);
}
function setGasLimitWithdrawRelay(uint256 _gas) public onlyValidator {
function setGasLimitWithdrawRelay(uint256 _gas) public onlyOwner {
gasLimitWithdrawRelay = _gas;
GasConsumptionLimitsUpdated(gasLimitWithdrawRelay);
}
function withdraw(uint8[] vs, bytes32[] rs, bytes32[] ss, bytes message) public {
require(message.length == 116);
// require(Helpers.hasEnoughValidSignatures(message, vs, rs, ss, validatorContract));

View File

@ -4,4 +4,5 @@ pragma solidity ^0.4.19;
interface IBridgeValidators {
function isValidator(address _validator) public view returns(bool);
function requiredSignatures() public view returns(uint8);
function currentOwner() public view returns(address);
}

View File

@ -10,6 +10,11 @@ contract Validatable {
_;
}
modifier onlyOwner() {
require(validatorContract.currentOwner() == msg.sender);
_;
}
function Validatable(address _validatorContract) public {
require(_validatorContract != address(0));
validatorContract = IBridgeValidators(_validatorContract);

View File

@ -1,6 +1,6 @@
pragma solidity 0.4.19;
import "../IBridgeValidators.sol";
import "./MessageSigning.sol";
library Helpers {
function addressArrayContains(address[] array, address value) internal pure returns (bool) {
@ -56,3 +56,25 @@ library Helpers {
return true;
}
}
library MessageSigning {
function recoverAddressFromSignedMessage(bytes signature, bytes message) internal pure returns (address) {
require(signature.length == 65);
bytes32 r;
bytes32 s;
bytes1 v;
// solium-disable-next-line security/no-inline-assembly
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := mload(add(signature, 0x60))
}
return ecrecover(hashMessage(message), uint8(v), r, s);
}
function hashMessage(bytes message) internal pure returns (bytes32) {
bytes memory prefix = "\x19Ethereum Signed Message:\n";
return keccak256(prefix, Helpers.uintToString(message.length), message);
}
}

View File

@ -1,23 +0,0 @@
pragma solidity 0.4.19;
import "./Helpers.sol";
library MessageSigning {
function recoverAddressFromSignedMessage(bytes signature, bytes message) internal pure returns (address) {
require(signature.length == 65);
bytes32 r;
bytes32 s;
bytes1 v;
// solium-disable-next-line security/no-inline-assembly
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := mload(add(signature, 0x60))
}
return ecrecover(hashMessage(message), uint8(v), r, s);
}
function hashMessage(bytes message) internal pure returns (bytes32) {
bytes memory prefix = "\x19Ethereum Signed Message:\n";
return keccak256(prefix, Helpers.uintToString(message.length), message);
}
}

View File

@ -1,10 +1,11 @@
pragma solidity 0.4.20;
pragma solidity ^0.4.19;
// File: contracts/IBridgeValidators.sol
interface IBridgeValidators {
function isValidator(address _validator) public view returns(bool);
function requiredSignatures() public view returns(uint8);
function currentOwner() public view returns(address);
}
// File: zeppelin-solidity/contracts/ownership/Ownable.sol
@ -98,4 +99,8 @@ contract BridgeValidators is Ownable, IBridgeValidators {
function requiredSignatures() public view returns(uint8) {
return requiredValidators;
}
function currentOwner() public view returns(address) {
return owner;
}
}

View File

@ -1,4 +1,4 @@
pragma solidity 0.4.20;
pragma solidity 0.4.19;
// File: contracts/BridgeDeploymentAddressStorage.sol
@ -21,6 +21,7 @@ contract ERC677Receiver {
interface IBridgeValidators {
function isValidator(address _validator) public view returns(bool);
function requiredSignatures() public view returns(uint8);
function currentOwner() public view returns(address);
}
// File: zeppelin-solidity/contracts/token/ERC20/ERC20Basic.sol
@ -55,7 +56,7 @@ contract ERC20 is ERC20Basic {
contract ERC677 is ERC20 {
event Transfer(address indexed from, address indexed to, uint value, bytes data);
function transferAndCall(address, uint, bytes) returns (bool);
function transferAndCall(address, uint, bytes) public returns (bool);
}
@ -76,91 +77,17 @@ contract Validatable {
_;
}
modifier onlyOwner() {
require(validatorContract.currentOwner() == msg.sender);
_;
}
function Validatable(address _validatorContract) public {
require(_validatorContract != address(0));
validatorContract = IBridgeValidators(_validatorContract);
}
}
// File: contracts/libraries/MessageSigning.sol
// import "./Helpers.sol";
library Helpers {
function addressArrayContains(address[] array, address value) internal pure returns (bool) {
for (uint256 i = 0; i < array.length; i++) {
if (array[i] == value) {
return true;
}
}
return false;
}
function uintToString(uint256 inputValue) internal pure returns (string) {
// figure out the length of the resulting string
uint256 length = 0;
uint256 currentValue = inputValue;
do {
length++;
currentValue /= 10;
} while (currentValue != 0);
// allocate enough memory
bytes memory result = new bytes(length);
// construct the string backwards
uint256 i = length - 1;
currentValue = inputValue;
do {
result[i--] = byte(48 + currentValue % 10);
currentValue /= 10;
} while (currentValue != 0);
return string(result);
}
function hasEnoughValidSignatures(
bytes _message,
uint8[] _vs,
bytes32[] _rs,
bytes32[] _ss,
IBridgeValidators _validatorContract) internal view returns (bool) {
uint8 _requiredSignatures = _validatorContract.requiredSignatures();
require(_vs.length < _requiredSignatures);
bytes32 hash = MessageSigning.hashMessage(_message);
address[] memory encounteredAddresses = new address[](_requiredSignatures);
for (uint8 i = 0; i < _requiredSignatures; i++) {
address recoveredAddress = ecrecover(hash, _vs[i], _rs[i], _ss[i]);
// only signatures by addresses in `addresses` are allowed
require(_validatorContract.isValidator(recoveredAddress));
// duplicate signatures are not allowed
if (addressArrayContains(encounteredAddresses, recoveredAddress)) {
return false;
}
encounteredAddresses[i] = recoveredAddress;
}
return true;
}
}
library MessageSigning {
function recoverAddressFromSignedMessage(bytes signature, bytes message) internal pure returns (address) {
require(signature.length == 65);
bytes32 r;
bytes32 s;
bytes1 v;
// solium-disable-next-line security/no-inline-assembly
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := mload(add(signature, 0x60))
}
return ecrecover(hashMessage(message), uint8(v), r, s);
}
function hashMessage(bytes message) internal pure returns (bytes32) {
bytes memory prefix = "\x19Ethereum Signed Message:\n";
return keccak256(prefix, Helpers.uintToString(message.length), message);
}
}
// File: contracts/libraries/Helpers.sol
library Helpers {
@ -218,6 +145,28 @@ library Helpers {
}
}
library MessageSigning {
function recoverAddressFromSignedMessage(bytes signature, bytes message) internal pure returns (address) {
require(signature.length == 65);
bytes32 r;
bytes32 s;
bytes1 v;
// solium-disable-next-line security/no-inline-assembly
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := mload(add(signature, 0x60))
}
return ecrecover(hashMessage(message), uint8(v), r, s);
}
function hashMessage(bytes message) internal pure returns (bytes32) {
bytes memory prefix = "\x19Ethereum Signed Message:\n";
return keccak256(prefix, Helpers.uintToString(message.length), message);
}
}
// File: contracts/libraries/Message.sol
library Message {
@ -285,12 +234,9 @@ contract ForeignBridge is ERC677Receiver, Validatable, BridgeDeploymentAddressSt
mapping (bytes32 => bytes) messages;
mapping (bytes32 => bytes) signatures;
mapping (bytes32 => bool) messages_signed;
mapping (bytes32 => uint) num_messages_signed;
mapping (bytes32 => uint256) num_messages_signed;
mapping (bytes32 => bool) deposits_signed;
mapping (bytes32 => uint) num_deposits_signed;
mapping (bytes32 => bool) tokenAddressApprovalSigns;
mapping (address => uint256) public numTokenAddressApprovalSigns;
mapping (bytes32 => uint256) num_deposits_signed;
IBurnableMintableERC677Token public erc677token;
@ -303,10 +249,11 @@ contract ForeignBridge is ERC677Receiver, Validatable, BridgeDeploymentAddressSt
/// Collected signatures which should be relayed to home chain.
event CollectedSignatures(address authorityResponsibleForRelay, bytes32 messageHash);
event TokenAddress(address token);
event GasConsumptionLimitsUpdated(uint256 gasLimitDepositRelay, uint256 gasLimitWithdrawConfirm);
event SignedForDeposit(address indexed signer, bytes32 message);
event SignedForWithdraw(address indexed signer, bytes32 message);
function ForeignBridge(
address _validatorContract,
address _erc677token
@ -314,13 +261,13 @@ contract ForeignBridge is ERC677Receiver, Validatable, BridgeDeploymentAddressSt
erc677token = IBurnableMintableERC677Token(_erc677token);
}
function setGasLimitDepositRelay(uint256 gas) onlyValidator {
gasLimitDepositRelay = gas;
function setGasLimitDepositRelay(uint256 _gas) public onlyOwner {
gasLimitDepositRelay = _gas;
GasConsumptionLimitsUpdated(gasLimitDepositRelay, gasLimitWithdrawConfirm);
}
function setGasLimitWithdrawConfirm(uint256 gas) onlyValidator {
function setGasLimitWithdrawConfirm(uint256 gas) public onlyOwner {
gasLimitWithdrawConfirm = gas;
GasConsumptionLimitsUpdated(gasLimitDepositRelay, gasLimitWithdrawConfirm);
@ -337,15 +284,18 @@ contract ForeignBridge is ERC677Receiver, Validatable, BridgeDeploymentAddressSt
require(!deposits_signed[hash_sender]);
deposits_signed[hash_sender] = true;
uint signed = num_deposits_signed[hash_msg] + 1;
uint256 signed = num_deposits_signed[hash_msg] + 1;
num_deposits_signed[hash_msg] = signed;
SignedForDeposit(msg.sender, transactionHash);
if (signed == validatorContract.requiredSignatures()) {
// If the bridge contract does not own enough tokens to transfer
// it will couse funds lock on the home side of the bridge
erc677token.mint(recipient, value);
Deposit(recipient, value);
}
}
function onTokenTransfer(address _from, uint256 _value, bytes _data) external returns(bool) {
@ -391,6 +341,7 @@ contract ForeignBridge is ERC677Receiver, Validatable, BridgeDeploymentAddressSt
num_messages_signed[hash_sender] = signed;
// TODO: this may cause troubles if requiredSignatures len is changed
SignedForWithdraw(msg.sender, hash);
if (signed == validatorContract.requiredSignatures()) {
CollectedSignatures(msg.sender, hash);
}

View File

@ -1,4 +1,4 @@
pragma solidity 0.4.20;
pragma solidity 0.4.19;
// File: contracts/BridgeDeploymentAddressStorage.sol
@ -15,6 +15,7 @@ contract BridgeDeploymentAddressStorage {
interface IBridgeValidators {
function isValidator(address _validator) public view returns(bool);
function requiredSignatures() public view returns(uint8);
function currentOwner() public view returns(address);
}
// File: contracts/Validatable.sol
@ -27,12 +28,96 @@ contract Validatable {
_;
}
modifier onlyOwner() {
require(validatorContract.currentOwner() == msg.sender);
_;
}
function Validatable(address _validatorContract) public {
require(_validatorContract != address(0));
validatorContract = IBridgeValidators(_validatorContract);
}
}
// File: contracts/libraries/Helpers.sol
library Helpers {
function addressArrayContains(address[] array, address value) internal pure returns (bool) {
for (uint256 i = 0; i < array.length; i++) {
if (array[i] == value) {
return true;
}
}
return false;
}
function uintToString(uint256 inputValue) internal pure returns (string) {
// figure out the length of the resulting string
uint256 length = 0;
uint256 currentValue = inputValue;
do {
length++;
currentValue /= 10;
} while (currentValue != 0);
// allocate enough memory
bytes memory result = new bytes(length);
// construct the string backwards
uint256 i = length - 1;
currentValue = inputValue;
do {
result[i--] = byte(48 + currentValue % 10);
currentValue /= 10;
} while (currentValue != 0);
return string(result);
}
function hasEnoughValidSignatures(
bytes _message,
uint8[] _vs,
bytes32[] _rs,
bytes32[] _ss,
IBridgeValidators _validatorContract) internal view returns (bool) {
uint8 _requiredSignatures = _validatorContract.requiredSignatures();
require(_vs.length < _requiredSignatures);
bytes32 hash = MessageSigning.hashMessage(_message);
address[] memory encounteredAddresses = new address[](_requiredSignatures);
for (uint8 i = 0; i < _requiredSignatures; i++) {
address recoveredAddress = ecrecover(hash, _vs[i], _rs[i], _ss[i]);
// only signatures by addresses in `addresses` are allowed
require(_validatorContract.isValidator(recoveredAddress));
// duplicate signatures are not allowed
if (addressArrayContains(encounteredAddresses, recoveredAddress)) {
return false;
}
encounteredAddresses[i] = recoveredAddress;
}
return true;
}
}
library MessageSigning {
function recoverAddressFromSignedMessage(bytes signature, bytes message) internal pure returns (address) {
require(signature.length == 65);
bytes32 r;
bytes32 s;
bytes1 v;
// solium-disable-next-line security/no-inline-assembly
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := mload(add(signature, 0x60))
}
return ecrecover(hashMessage(message), uint8(v), r, s);
}
function hashMessage(bytes message) internal pure returns (bytes32) {
bytes memory prefix = "\x19Ethereum Signed Message:\n";
return keccak256(prefix, Helpers.uintToString(message.length), message);
}
}
// File: contracts/libraries/Message.sol
library Message {
@ -91,85 +176,6 @@ library Message {
}
}
// File: contracts/libraries/MessageSigning.sol
// import "./Helpers.sol";
library Helpers {
function addressArrayContains(address[] array, address value) internal pure returns (bool) {
for (uint256 i = 0; i < array.length; i++) {
if (array[i] == value) {
return true;
}
}
return false;
}
function uintToString(uint256 inputValue) internal pure returns (string) {
// figure out the length of the resulting string
uint256 length = 0;
uint256 currentValue = inputValue;
do {
length++;
currentValue /= 10;
} while (currentValue != 0);
// allocate enough memory
bytes memory result = new bytes(length);
// construct the string backwards
uint256 i = length - 1;
currentValue = inputValue;
do {
result[i--] = byte(48 + currentValue % 10);
currentValue /= 10;
} while (currentValue != 0);
return string(result);
}
function hasEnoughValidSignatures(
bytes _message,
uint8[] _vs,
bytes32[] _rs,
bytes32[] _ss,
IBridgeValidators _validatorContract) internal view returns (bool) {
uint8 _requiredSignatures = _validatorContract.requiredSignatures();
require(_vs.length < _requiredSignatures);
bytes32 hash = MessageSigning.hashMessage(_message);
address[] memory encounteredAddresses = new address[](_requiredSignatures);
for (uint8 i = 0; i < _requiredSignatures; i++) {
address recoveredAddress = ecrecover(hash, _vs[i], _rs[i], _ss[i]);
// only signatures by addresses in `addresses` are allowed
require(_validatorContract.isValidator(recoveredAddress));
// duplicate signatures are not allowed
if (addressArrayContains(encounteredAddresses, recoveredAddress)) {
return false;
}
encounteredAddresses[i] = recoveredAddress;
}
return true;
}
}
library MessageSigning {
function recoverAddressFromSignedMessage(bytes signature, bytes message) internal pure returns (address) {
require(signature.length == 65);
bytes32 r;
bytes32 s;
bytes1 v;
// solium-disable-next-line security/no-inline-assembly
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := mload(add(signature, 0x60))
}
return ecrecover(hashMessage(message), uint8(v), r, s);
}
function hashMessage(bytes message) internal pure returns (bytes32) {
bytes memory prefix = "\x19Ethereum Signed Message:\n";
return keccak256(prefix, Helpers.uintToString(message.length), message);
}
}
// File: contracts/libraries/SafeMath.sol
/**
@ -220,14 +226,6 @@ library SafeMath {
// File: contracts/HomeBridge.sol
// import "./libraries/Helpers.sol";
contract HomeBridge is Validatable, BridgeDeploymentAddressStorage {
using SafeMath for uint256;
uint256 public gasLimitWithdrawRelay;
@ -248,11 +246,12 @@ contract HomeBridge is Validatable, BridgeDeploymentAddressStorage {
Deposit(msg.sender, msg.value);
}
function setGasLimitWithdrawRelay(uint256 _gas) public onlyValidator {
function setGasLimitWithdrawRelay(uint256 _gas) public onlyOwner {
gasLimitWithdrawRelay = _gas;
GasConsumptionLimitsUpdated(gasLimitWithdrawRelay);
}
function withdraw(uint8[] vs, bytes32[] rs, bytes32[] ss, bytes message) public {
require(message.length == 116);
// require(Helpers.hasEnoughValidSignatures(message, vs, rs, ss, validatorContract));

View File

@ -1,4 +1,4 @@
pragma solidity 0.4.20;
pragma solidity 0.4.19;
// File: contracts/ERC677Receiver.sol
@ -38,7 +38,7 @@ contract ERC20 is ERC20Basic {
contract ERC677 is ERC20 {
event Transfer(address indexed from, address indexed to, uint value, bytes data);
function transferAndCall(address, uint, bytes) returns (bool);
function transferAndCall(address, uint, bytes) public returns (bool);
}

7
flatten.sh Executable file
View File

@ -0,0 +1,7 @@
#!/usr/bin/env bash
rm -rf flats/*
./node_modules/.bin/truffle-flattener contracts/ForeignBridge.sol > flats/ForeignBridge_flat.sol
./node_modules/.bin/truffle-flattener contracts/BridgeValidators.sol > flats/BridgeValidators_flat.sol
./node_modules/.bin/truffle-flattener contracts/HomeBridge.sol > flats/HomeBridge_flat.sol
./node_modules/.bin/truffle-flattener contracts/POA20.sol > flats/POA20_flat.sol

View File

@ -4,11 +4,16 @@ const HomeBridge = artifacts.require("./HomeBridge.sol");
const ForeignBridge = artifacts.require("./ForeignBridge.sol");
module.exports = async function(deployer, network, accounts) {
let validators = ["0xb8988b690910913c97a090c3a6f80fad8b3a4683"]
console.log('deploying token')
await deployer.deploy(POA20, "POA ERC20 on Foundation", "POA20", 18)
const erc677token = await POA20.deployed()
await deployer.deploy(BridgeValidators, '1', [accounts[0]]);
console.log('deploying validators')
await deployer.deploy(BridgeValidators, '1', validators);
const validatorContract = await BridgeValidators.deployed();
console.log('deploying home')
await deployer.deploy(HomeBridge, validatorContract.address);
console.log('deploying ForeignBridge')
await deployer.deploy(ForeignBridge, validatorContract.address, erc677token.address);
const foreignBridge = await ForeignBridge.deployed();

427
package-lock.json generated
View File

@ -4,16 +4,41 @@
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"ajv": {
"version": "5.5.2",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
"integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
"dev": true,
"requires": {
"co": "4.6.0",
"fast-deep-equal": "1.1.0",
"fast-json-stable-stringify": "2.0.0",
"json-schema-traverse": "0.3.1"
}
},
"ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
},
"async": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz",
"integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==",
"dev": true,
"requires": {
"lodash": "4.17.5"
}
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
},
"bignumber.js": {
"version": "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934",
"dev": true
},
"bn.js": {
"version": "4.11.6",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz",
@ -53,6 +78,12 @@
"wrap-ansi": "2.1.0"
}
},
"co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
"dev": true
},
"code-point-at": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
@ -71,6 +102,12 @@
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"crypto-js": {
"version": "3.1.8",
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.8.tgz",
"integrity": "sha1-cV8HC/YBTyrpkqmLOSkli3E/CNU=",
"dev": true
},
"debug": {
"version": "2.6.8",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz",
@ -117,6 +154,18 @@
"number-to-bn": "1.7.0"
}
},
"fast-deep-equal": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz",
"integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=",
"dev": true
},
"fast-json-stable-stringify": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
"dev": true
},
"find-up": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
@ -241,11 +290,41 @@
"resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
"integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI="
},
"jade": {
"version": "0.26.3",
"resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz",
"integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=",
"dev": true,
"requires": {
"commander": "0.6.1",
"mkdirp": "0.3.0"
},
"dependencies": {
"commander": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz",
"integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=",
"dev": true
},
"mkdirp": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz",
"integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=",
"dev": true
}
}
},
"js-sha3": {
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.5.tgz",
"integrity": "sha1-uvDA6MVK1ZA0R9+Wreekobynmko="
},
"json-schema-traverse": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz",
"integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=",
"dev": true
},
"json3": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz",
@ -287,6 +366,30 @@
"strip-bom": "2.0.0"
}
},
"locate-path": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
"integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
"dev": true,
"requires": {
"p-locate": "2.0.0",
"path-exists": "3.0.0"
},
"dependencies": {
"path-exists": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
"integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
"dev": true
}
}
},
"lodash": {
"version": "4.17.5",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz",
"integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==",
"dev": true
},
"lodash._baseassign": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz",
@ -351,6 +454,12 @@
"lodash.isarray": "3.0.4"
}
},
"lru-cache": {
"version": "2.7.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz",
"integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=",
"dev": true
},
"memorystream": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
@ -447,6 +556,30 @@
"lcid": "1.0.0"
}
},
"p-limit": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz",
"integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==",
"dev": true,
"requires": {
"p-try": "1.0.0"
}
},
"p-locate": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
"integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
"dev": true,
"requires": {
"p-limit": "1.2.0"
}
},
"p-try": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
"integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=",
"dev": true
},
"parse-json": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
@ -478,6 +611,12 @@
"pinkie-promise": "2.0.1"
}
},
"pegjs": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/pegjs/-/pegjs-0.10.0.tgz",
"integrity": "sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0=",
"dev": true
},
"pify": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
@ -548,6 +687,12 @@
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
},
"sigmund": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz",
"integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=",
"dev": true
},
"solc": {
"version": "0.4.19",
"resolved": "https://registry.npmjs.org/solc/-/solc-0.4.19.tgz",
@ -560,6 +705,96 @@
"yargs": "4.8.1"
}
},
"solidity-parser": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/solidity-parser/-/solidity-parser-0.4.0.tgz",
"integrity": "sha1-o0PxPac8kWgyeQNGgOgMSR3jQPo=",
"dev": true,
"requires": {
"mocha": "2.5.3",
"pegjs": "0.10.0",
"yargs": "4.8.1"
},
"dependencies": {
"commander": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz",
"integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=",
"dev": true
},
"debug": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz",
"integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=",
"dev": true,
"requires": {
"ms": "0.7.1"
}
},
"diff": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz",
"integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=",
"dev": true
},
"escape-string-regexp": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz",
"integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=",
"dev": true
},
"glob": {
"version": "3.2.11",
"resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz",
"integrity": "sha1-Spc/Y1uRkPcV0QmH1cAP0oFevj0=",
"dev": true,
"requires": {
"inherits": "2.0.3",
"minimatch": "0.3.0"
}
},
"minimatch": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz",
"integrity": "sha1-J12O2qxPG7MyZHIInnlJyDlGmd0=",
"dev": true,
"requires": {
"lru-cache": "2.7.3",
"sigmund": "1.0.1"
}
},
"mocha": {
"version": "2.5.3",
"resolved": "https://registry.npmjs.org/mocha/-/mocha-2.5.3.tgz",
"integrity": "sha1-FhvlvetJZ3HrmzV0UFC2IrWu/Fg=",
"dev": true,
"requires": {
"commander": "2.3.0",
"debug": "2.2.0",
"diff": "1.4.0",
"escape-string-regexp": "1.0.2",
"glob": "3.2.11",
"growl": "1.9.2",
"jade": "0.26.3",
"mkdirp": "0.5.1",
"supports-color": "1.2.0",
"to-iso-string": "0.0.2"
}
},
"ms": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz",
"integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=",
"dev": true
},
"supports-color": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.2.0.tgz",
"integrity": "sha1-/x7R5hFp0Gs88tWI4YixjYhH4X4=",
"dev": true
}
}
},
"spdx-correct": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz",
@ -620,6 +855,12 @@
"has-flag": "1.0.0"
}
},
"to-iso-string": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/to-iso-string/-/to-iso-string-0.0.2.tgz",
"integrity": "sha1-TcGeZk38y+Jb2NtQiwDG2hWCVdE=",
"dev": true
},
"truffle": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/truffle/-/truffle-4.0.6.tgz",
@ -630,6 +871,167 @@
"solc": "0.4.19"
}
},
"truffle-blockchain-utils": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/truffle-blockchain-utils/-/truffle-blockchain-utils-0.0.4.tgz",
"integrity": "sha512-wgRrhwqh0aea08Hz28hUV4tuF2uTVQH/e9kBou+WK04cqrutB5cxQVQ6HGjeZLltxBYOFvhrGOOq4l3WJFnPEA==",
"dev": true
},
"truffle-config": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/truffle-config/-/truffle-config-1.0.4.tgz",
"integrity": "sha512-E8pvJNAIjs7LNsjkYeS2dgoOnLoSBrTwb1xF5lJwfvZmGMFpKvVL1sa5jpFxozpf/WkRn/rfxy8zTdb3pq16jA==",
"dev": true,
"requires": {
"find-up": "2.1.0",
"lodash": "4.17.5",
"original-require": "1.0.1",
"truffle-error": "0.0.2",
"truffle-provider": "0.0.4"
},
"dependencies": {
"find-up": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
"integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
"dev": true,
"requires": {
"locate-path": "2.0.0"
}
}
}
},
"truffle-contract": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/truffle-contract/-/truffle-contract-3.0.4.tgz",
"integrity": "sha512-/1LCtJFf5Jvm5Rv88T0d/rZSKvaiW/yO1SHXLGJgKzLsiG1F/2spFs4HrI1mRxP00opfrYXloEmLtkVV/kcndQ==",
"dev": true,
"requires": {
"ethjs-abi": "0.1.8",
"truffle-blockchain-utils": "0.0.4",
"truffle-contract-schema": "2.0.0",
"truffle-error": "0.0.2",
"web3": "0.20.5"
},
"dependencies": {
"ethjs-abi": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/ethjs-abi/-/ethjs-abi-0.1.8.tgz",
"integrity": "sha1-zSiFg+1ijN+tr4re+juh28vKbBg=",
"dev": true,
"requires": {
"bn.js": "4.11.6",
"js-sha3": "0.5.5",
"number-to-bn": "1.7.0"
}
}
}
},
"truffle-contract-schema": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/truffle-contract-schema/-/truffle-contract-schema-2.0.0.tgz",
"integrity": "sha512-nLlspmu1GKDaluWksBwitHi/7Z3IpRjmBYeO9N+T1nVJD2V4IWJaptCKP1NqnPiJA+FChB7+F7pI6Br51/FtXQ==",
"dev": true,
"requires": {
"ajv": "5.5.2",
"crypto-js": "3.1.9-1",
"debug": "3.1.0"
},
"dependencies": {
"crypto-js": {
"version": "3.1.9-1",
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-3.1.9-1.tgz",
"integrity": "sha1-/aGedh/Ad+Af+/3G6f38WeiAbNg=",
"dev": true
},
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"dev": true,
"requires": {
"ms": "2.0.0"
}
}
}
},
"truffle-error": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/truffle-error/-/truffle-error-0.0.2.tgz",
"integrity": "sha1-AbGJt4UFVmrhaJwjnHyi3RIc/kw=",
"dev": true
},
"truffle-expect": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/truffle-expect/-/truffle-expect-0.0.3.tgz",
"integrity": "sha1-m3XO80O9WW5+XbyHj18bLjGKlEw=",
"dev": true
},
"truffle-flattener": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/truffle-flattener/-/truffle-flattener-1.2.3.tgz",
"integrity": "sha512-DisthKMI1qH+Xbw/S84CLPGeXz/kMkVUxBpz8Elj2kI4paVjEFEFwrq0juQHwxr2w/046r2tUT5usCE38Bw6Qw==",
"dev": true,
"requires": {
"find-up": "2.1.0",
"semver": "5.5.0",
"solidity-parser": "0.4.0",
"truffle-config": "1.0.4",
"truffle-resolver": "4.0.2",
"tsort": "0.0.1"
},
"dependencies": {
"find-up": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
"integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
"dev": true,
"requires": {
"locate-path": "2.0.0"
}
}
}
},
"truffle-provider": {
"version": "0.0.4",
"resolved": "https://registry.npmjs.org/truffle-provider/-/truffle-provider-0.0.4.tgz",
"integrity": "sha512-yVxxjocxnJcFspQ0T4Rjq/1wvvm3iLxidb6oa1EAX5LsnSQLPG8wAM5+JLlJ4FDBsqJdZLGOq1RR5Ln/w7x5JA==",
"dev": true,
"requires": {
"truffle-error": "0.0.2",
"web3": "0.20.5"
}
},
"truffle-provisioner": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/truffle-provisioner/-/truffle-provisioner-0.1.0.tgz",
"integrity": "sha1-Ap5SScEBUwBzhTXgT97ZMaU8T2I=",
"dev": true
},
"truffle-resolver": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/truffle-resolver/-/truffle-resolver-4.0.2.tgz",
"integrity": "sha512-HKRd45HSfAqb9/BCOgYq4zkyl2lF40MvPDIGhyoPXFj5/9PSFzclyTkkMOdb+Rnm7oC1vY4cE1/k453lgf81Kw==",
"dev": true,
"requires": {
"async": "2.6.0",
"truffle-contract": "3.0.4",
"truffle-expect": "0.0.3",
"truffle-provisioner": "0.1.0"
}
},
"tsort": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/tsort/-/tsort-0.0.1.tgz",
"integrity": "sha1-4igPXoF/i/QnVlf9D5rr1E9aJ4Y=",
"dev": true
},
"utf8": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/utf8/-/utf8-2.1.2.tgz",
"integrity": "sha1-H6DZJw6b6FDZsFAn9jUZv0ZFfZY=",
"dev": true
},
"validate-npm-package-license": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz",
@ -639,6 +1041,19 @@
"spdx-expression-parse": "1.0.4"
}
},
"web3": {
"version": "0.20.5",
"resolved": "https://registry.npmjs.org/web3/-/web3-0.20.5.tgz",
"integrity": "sha1-xQSNNfe/TixMKAzlH7u8lRKQsWU=",
"dev": true,
"requires": {
"bignumber.js": "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934",
"crypto-js": "3.1.8",
"utf8": "2.1.2",
"xhr2": "0.1.4",
"xmlhttprequest": "1.8.0"
}
},
"which-module": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz",
@ -663,6 +1078,18 @@
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
},
"xhr2": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/xhr2/-/xhr2-0.1.4.tgz",
"integrity": "sha1-f4dliEdxbbUCYyOBL4GMras4el8=",
"dev": true
},
"xmlhttprequest": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz",
"integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=",
"dev": true
},
"y18n": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",

View File

@ -4,15 +4,17 @@
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"test": "truffle test",
"deploy": "truffle migrate --reset --network $NETWORK",
"flatten": "bash flatten.sh"
},
"author": "",
"license": "ISC",
"scripts": {
"test": "truffle test"
},
"dependencies": {
"truffle": "^4.0.6",
"zeppelin-solidity": "^1.6.0"
},
"devDependencies": {
"truffle-flattener": "^1.2.3"
}
}