convert liquidPledging to accept a different token per pledge
This commit is contained in:
parent
46e87cffa1
commit
3ae23500c6
|
@ -49,6 +49,7 @@ contract ILiquidPledgingPlugin {
|
|||
uint64 pledgeFrom,
|
||||
uint64 pledgeTo,
|
||||
uint64 context,
|
||||
address token,
|
||||
uint amount ) public returns (uint maxAllowed);
|
||||
|
||||
/// @notice Plugins are used (much like web hooks) to initiate an action
|
||||
|
@ -76,6 +77,7 @@ contract ILiquidPledgingPlugin {
|
|||
uint64 pledgeFrom,
|
||||
uint64 pledgeTo,
|
||||
uint64 context,
|
||||
address token,
|
||||
uint amount
|
||||
) public;
|
||||
}
|
||||
|
|
|
@ -18,9 +18,6 @@ pragma solidity ^0.4.18;
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/// @title LPVault
|
||||
/// @author Jordi Baylina
|
||||
|
||||
/// @dev This contract holds ether securely for liquid pledging systems; for
|
||||
/// this iteration the funds will come often be escaped to the Giveth Multisig
|
||||
/// (safety precaution), but once fully tested and optimized this contract will
|
||||
|
@ -28,6 +25,7 @@ pragma solidity ^0.4.18;
|
|||
/// to allow for an optional escapeHatch to be implemented in case of issues;
|
||||
/// future versions of this contract will be enabled for tokens
|
||||
import "./EscapableApp.sol";
|
||||
import "giveth-common-contracts/contracts/ERC20.sol";
|
||||
|
||||
/// @dev `LiquidPledging` is a basic interface to allow the `LPVault` contract
|
||||
/// to confirm and cancel payments in the `LiquidPledging` contract.
|
||||
|
@ -53,6 +51,7 @@ contract LPVault is EscapableApp {
|
|||
uint indexed idPayment,
|
||||
bytes32 indexed ref,
|
||||
address indexed dest,
|
||||
address token,
|
||||
uint amount
|
||||
);
|
||||
|
||||
|
@ -66,9 +65,10 @@ contract LPVault is EscapableApp {
|
|||
/// each payment the `ref` param makes it easy to track the movements of
|
||||
/// funds transparently by its connection to other `Payment` structs
|
||||
struct Payment {
|
||||
PaymentStatus state; // Pending, Paid or Canceled
|
||||
bytes32 ref; // an input that references details from other contracts
|
||||
address dest; // recipient of the ETH
|
||||
PaymentStatus state; // Pending, Paid or Canceled
|
||||
address token;
|
||||
uint amount; // amount of ETH (in wei) to be sent
|
||||
}
|
||||
|
||||
|
@ -102,10 +102,6 @@ contract LPVault is EscapableApp {
|
|||
liquidPledging = ILiquidPledging(_liquidPledging);
|
||||
}
|
||||
|
||||
/// @dev The fall back function allows ETH to be deposited into the LPVault
|
||||
/// through a simple send
|
||||
function () public payable {}
|
||||
|
||||
/// @notice Used to decentralize, toggles whether the LPVault will
|
||||
/// automatically confirm a payment after the payment has been authorized
|
||||
/// @param _automatic If true, payments will confirm instantly, if false
|
||||
|
@ -126,6 +122,7 @@ contract LPVault is EscapableApp {
|
|||
function authorizePayment(
|
||||
bytes32 _ref,
|
||||
address _dest,
|
||||
address _token,
|
||||
uint _amount
|
||||
) external authP(AUTHORIZE_PAYMENT_ROLE, arr(_dest, _amount)) returns (uint)
|
||||
{
|
||||
|
@ -134,9 +131,10 @@ contract LPVault is EscapableApp {
|
|||
payments[idPayment].state = PaymentStatus.Pending;
|
||||
payments[idPayment].ref = _ref;
|
||||
payments[idPayment].dest = _dest;
|
||||
payments[idPayment].token = _token;
|
||||
payments[idPayment].amount = _amount;
|
||||
|
||||
AuthorizePayment(idPayment, _ref, _dest, _amount);
|
||||
AuthorizePayment(idPayment, _ref, _dest, _token, _amount);
|
||||
|
||||
if (autoPay) {
|
||||
_doConfirmPayment(idPayment);
|
||||
|
@ -177,20 +175,13 @@ contract LPVault is EscapableApp {
|
|||
}
|
||||
}
|
||||
|
||||
/// Transfer eth or tokens to the escapeHatchDestination.
|
||||
/// Transfer tokens to the escapeHatchDestination.
|
||||
/// Used as a safety mechanism to prevent the vault from holding too much value
|
||||
/// before being thoroughly battle-tested.
|
||||
/// @param _token to transfer, use 0x0 for ether
|
||||
/// @param _token to transfer
|
||||
/// @param _amount to transfer
|
||||
function escapeFunds(address _token, uint _amount) public authP(ESCAPE_HATCH_CALLER_ROLE, arr(_token)) {
|
||||
/// @dev Logic for ether
|
||||
if (_token == 0x0) {
|
||||
require(this.balance >= _amount);
|
||||
escapeHatchDestination.transfer(_amount);
|
||||
EscapeHatchCalled(_token, _amount);
|
||||
return;
|
||||
}
|
||||
/// @dev Logic for tokens
|
||||
require(_token != 0x0);
|
||||
ERC20 token = ERC20(_token);
|
||||
uint balance = token.balanceOf(this);
|
||||
require(balance >= _amount);
|
||||
|
@ -215,7 +206,8 @@ contract LPVault is EscapableApp {
|
|||
p.state = PaymentStatus.Paid;
|
||||
liquidPledging.confirmPayment(uint64(p.ref), p.amount);
|
||||
|
||||
p.dest.transfer(p.amount); // Transfers ETH denominated in wei
|
||||
ERC20 token = ERC20(p.token);
|
||||
require(token.transfer(p.dest, p.amount)); // Transfers token to dest
|
||||
|
||||
ConfirmPayment(_idPayment, p.ref);
|
||||
}
|
||||
|
|
|
@ -27,19 +27,19 @@ import "./LiquidPledgingBase.sol";
|
|||
/// to allow for expanded functionality.
|
||||
contract LiquidPledging is LiquidPledgingBase {
|
||||
|
||||
function addGiverAndDonate(uint64 idReceiver)
|
||||
public payable
|
||||
function addGiverAndDonate(uint64 idReceiver, address token, uint amount)
|
||||
public
|
||||
{
|
||||
addGiverAndDonate(idReceiver, msg.sender);
|
||||
addGiverAndDonate(idReceiver, msg.sender, token, amount);
|
||||
}
|
||||
|
||||
function addGiverAndDonate(uint64 idReceiver, address donorAddress)
|
||||
public payable
|
||||
function addGiverAndDonate(uint64 idReceiver, address donorAddress, address token, uint amount)
|
||||
public
|
||||
{
|
||||
require(donorAddress != 0);
|
||||
// default to a 3 day (259200 seconds) commitTime
|
||||
uint64 idGiver = _addGiver(donorAddress, "", "", 259200, ILiquidPledgingPlugin(0));
|
||||
donate(idGiver, idReceiver);
|
||||
donate(idGiver, idReceiver, token, amount);
|
||||
}
|
||||
|
||||
/// @notice This is how value enters the system and how pledges are created;
|
||||
|
@ -50,19 +50,17 @@ contract LiquidPledging is LiquidPledgingBase {
|
|||
/// @param idGiver The id of the Giver donating; if 0, a new id is created
|
||||
/// @param idReceiver The Admin receiving the donation; can be any Admin:
|
||||
/// the Giver themselves, another Giver, a Delegate or a Project
|
||||
function donate(uint64 idGiver, uint64 idReceiver)
|
||||
public payable
|
||||
function donate(uint64 idGiver, uint64 idReceiver, address token, uint amount)
|
||||
public
|
||||
{
|
||||
require(idGiver > 0); // prevent burning donations. idReceiver is checked in _transfer
|
||||
require(amount > 0);
|
||||
require(token != 0x0);
|
||||
|
||||
PledgeAdmin storage sender = _findAdmin(idGiver);
|
||||
require(sender.adminType == PledgeAdminType.Giver);
|
||||
|
||||
uint amount = msg.value;
|
||||
require(amount > 0);
|
||||
// Sends the `msg.value` (in wei) to the `vault`
|
||||
// b/c the vault is a proxy, send & transfer will fail since they only provide 2300
|
||||
// gas, and the delegateProxy will sub(gas, 10000) before even making the call
|
||||
require(vault.call.value(amount).gas(16000)());
|
||||
require(ERC20(token).transferFrom(msg.sender, address(vault), amount)); // transfer the token to the `vault`
|
||||
|
||||
uint64 idPledge = _findOrCreatePledge(
|
||||
idGiver,
|
||||
|
@ -70,6 +68,7 @@ contract LiquidPledging is LiquidPledgingBase {
|
|||
0,
|
||||
0,
|
||||
0,
|
||||
token,
|
||||
PledgeState.Pledged
|
||||
);
|
||||
|
||||
|
@ -120,12 +119,13 @@ contract LiquidPledging is LiquidPledgingBase {
|
|||
0,
|
||||
0,
|
||||
p.oldPledge,
|
||||
p.token,
|
||||
PledgeState.Paying
|
||||
);
|
||||
|
||||
_doTransfer(idPledge, idNewPledge, amount);
|
||||
|
||||
vault.authorizePayment(bytes32(idNewPledge), owner.addr, amount);
|
||||
vault.authorizePayment(bytes32(idNewPledge), owner.addr, p.token, amount);
|
||||
}
|
||||
|
||||
/// @notice `onlyVault` Confirms a withdraw request changing the PledgeState
|
||||
|
@ -143,6 +143,7 @@ contract LiquidPledging is LiquidPledgingBase {
|
|||
0,
|
||||
0,
|
||||
p.oldPledge,
|
||||
p.token,
|
||||
PledgeState.Paid
|
||||
);
|
||||
|
||||
|
@ -165,6 +166,7 @@ contract LiquidPledging is LiquidPledgingBase {
|
|||
0,
|
||||
0,
|
||||
p.oldPledge,
|
||||
p.token,
|
||||
PledgeState.Pledged
|
||||
);
|
||||
|
||||
|
@ -177,7 +179,6 @@ contract LiquidPledging is LiquidPledgingBase {
|
|||
/// @param idProject Id of the project that is to be canceled
|
||||
function cancelProject(uint64 idProject) authP(PLEDGE_ADMIN_ROLE, arr(uint(idProject))) public {
|
||||
PledgeAdmin storage project = _findAdmin(idProject);
|
||||
// _checkAdminOwner(project);
|
||||
project.canceled = true;
|
||||
|
||||
CancelProject(idProject);
|
||||
|
|
|
@ -122,6 +122,7 @@ contract LiquidPledgingBase is EscapableApp, LiquidPledgingStorage, PledgeAdmins
|
|||
0,
|
||||
0,
|
||||
p.oldPledge,
|
||||
p.token,
|
||||
PledgeState.Pledged
|
||||
);
|
||||
uint64 toPledge = _findOrCreatePledge(
|
||||
|
@ -130,6 +131,7 @@ contract LiquidPledgingBase is EscapableApp, LiquidPledgingStorage, PledgeAdmins
|
|||
0,
|
||||
0,
|
||||
oldPledge,
|
||||
p.token,
|
||||
PledgeState.Pledged
|
||||
);
|
||||
_doTransfer(idPledge, toPledge, p.amount);
|
||||
|
@ -186,6 +188,7 @@ contract LiquidPledgingBase is EscapableApp, LiquidPledgingStorage, PledgeAdmins
|
|||
0,
|
||||
0,
|
||||
p.oldPledge,
|
||||
p.token,
|
||||
PledgeState.Pledged);
|
||||
_doTransfer(idPledge, toPledge, amount);
|
||||
} else {
|
||||
|
@ -203,7 +206,7 @@ contract LiquidPledgingBase is EscapableApp, LiquidPledgingStorage, PledgeAdmins
|
|||
}
|
||||
|
||||
} else {
|
||||
// This should never be reached as the reciever.adminType
|
||||
// This should never be reached as the receiver.adminType
|
||||
// should always be either a Giver, Project, or Delegate
|
||||
assert(false);
|
||||
}
|
||||
|
@ -299,6 +302,7 @@ contract LiquidPledgingBase is EscapableApp, LiquidPledgingStorage, PledgeAdmins
|
|||
0,
|
||||
0,
|
||||
p.oldPledge,
|
||||
p.token,
|
||||
PledgeState.Pledged
|
||||
);
|
||||
uint64 toPledge = _findOrCreatePledge(
|
||||
|
@ -306,7 +310,8 @@ contract LiquidPledgingBase is EscapableApp, LiquidPledgingStorage, PledgeAdmins
|
|||
new uint64[](0), // clear the delegation chain
|
||||
0,
|
||||
0,
|
||||
uint64(oldPledge),
|
||||
oldPledge,
|
||||
p.token,
|
||||
PledgeState.Pledged
|
||||
);
|
||||
_doTransfer(idPledge, toPledge, amount);
|
||||
|
@ -316,8 +321,8 @@ contract LiquidPledgingBase is EscapableApp, LiquidPledgingStorage, PledgeAdmins
|
|||
/// @notice `transferOwnershipToGiver` allows for the transfer of
|
||||
/// value back to the Giver, value is placed in a pledged state
|
||||
/// without being attached to a project, delegation chain, or time line.
|
||||
/// @param idPledge the id of the pledge to be transfered.
|
||||
/// @param amount Quantity of value that's being transfered
|
||||
/// @param idPledge the id of the pledge to be transferred.
|
||||
/// @param amount Quantity of value that's being transferred
|
||||
/// @param idReceiver The new owner of the pledge
|
||||
function _transferOwnershipToGiver(
|
||||
uint64 idPledge,
|
||||
|
@ -325,12 +330,15 @@ contract LiquidPledgingBase is EscapableApp, LiquidPledgingStorage, PledgeAdmins
|
|||
uint64 idReceiver
|
||||
) internal
|
||||
{
|
||||
Pledge storage p = _findPledge(idPledge);
|
||||
|
||||
uint64 toPledge = _findOrCreatePledge(
|
||||
idReceiver,
|
||||
new uint64[](0),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
p.token,
|
||||
PledgeState.Pledged
|
||||
);
|
||||
_doTransfer(idPledge, toPledge, amount);
|
||||
|
@ -366,6 +374,7 @@ contract LiquidPledgingBase is EscapableApp, LiquidPledgingStorage, PledgeAdmins
|
|||
0,
|
||||
0,
|
||||
p.oldPledge,
|
||||
p.token,
|
||||
PledgeState.Pledged
|
||||
);
|
||||
_doTransfer(idPledge, toPledge, amount);
|
||||
|
@ -397,6 +406,7 @@ contract LiquidPledgingBase is EscapableApp, LiquidPledgingStorage, PledgeAdmins
|
|||
0,
|
||||
0,
|
||||
p.oldPledge,
|
||||
p.token,
|
||||
PledgeState.Pledged
|
||||
);
|
||||
_doTransfer(idPledge, toPledge, amount);
|
||||
|
@ -426,6 +436,7 @@ contract LiquidPledgingBase is EscapableApp, LiquidPledgingStorage, PledgeAdmins
|
|||
idReceiver,
|
||||
uint64(_getTime() + _maxCommitTime(p)),
|
||||
p.oldPledge,
|
||||
p.token,
|
||||
PledgeState.Pledged
|
||||
);
|
||||
_doTransfer(idPledge, toPledge, amount);
|
||||
|
@ -520,6 +531,7 @@ contract LiquidPledgingBase is EscapableApp, LiquidPledgingStorage, PledgeAdmins
|
|||
uint64 fromPledge,
|
||||
uint64 toPledge,
|
||||
uint64 context,
|
||||
address token,
|
||||
uint amount
|
||||
) internal returns (uint allowedAmount)
|
||||
{
|
||||
|
@ -537,6 +549,7 @@ contract LiquidPledgingBase is EscapableApp, LiquidPledgingStorage, PledgeAdmins
|
|||
fromPledge,
|
||||
toPledge,
|
||||
context,
|
||||
token,
|
||||
amount
|
||||
);
|
||||
require(newAmount <= allowedAmount);
|
||||
|
@ -547,6 +560,7 @@ contract LiquidPledgingBase is EscapableApp, LiquidPledgingStorage, PledgeAdmins
|
|||
fromPledge,
|
||||
toPledge,
|
||||
context,
|
||||
token,
|
||||
amount
|
||||
);
|
||||
}
|
||||
|
@ -585,6 +599,7 @@ contract LiquidPledgingBase is EscapableApp, LiquidPledgingStorage, PledgeAdmins
|
|||
fromPledge,
|
||||
toPledge,
|
||||
offset,
|
||||
p.token,
|
||||
allowedAmount
|
||||
);
|
||||
|
||||
|
@ -596,6 +611,7 @@ contract LiquidPledgingBase is EscapableApp, LiquidPledgingStorage, PledgeAdmins
|
|||
fromPledge,
|
||||
toPledge,
|
||||
offset + i + 1,
|
||||
p.token,
|
||||
allowedAmount
|
||||
);
|
||||
}
|
||||
|
@ -610,6 +626,7 @@ contract LiquidPledgingBase is EscapableApp, LiquidPledgingStorage, PledgeAdmins
|
|||
fromPledge,
|
||||
toPledge,
|
||||
offset + 255,
|
||||
p.token,
|
||||
allowedAmount
|
||||
);
|
||||
}
|
||||
|
|
|
@ -6,8 +6,7 @@ import "./ILiquidPledgingPlugin.sol";
|
|||
/// the ETH that backs the Pledges, only after `LiquidPledging` authorizes
|
||||
/// payments can Pledges be converted for ETH
|
||||
interface ILPVault {
|
||||
function authorizePayment(bytes32 _ref, address _dest, uint _amount) public;
|
||||
function () public payable;
|
||||
function authorizePayment(bytes32 _ref, address _dest, address _token, uint _amount) public;
|
||||
}
|
||||
|
||||
/// This contract contains all state variables used in LiquidPledging contracts
|
||||
|
@ -46,6 +45,7 @@ contract LiquidPledgingStorage {
|
|||
uint64 intendedProject; // Used when delegates are sending to projects
|
||||
uint64 commitTime; // When the intendedProject will become the owner
|
||||
uint64 oldPledge; // Points to the id that this Pledge was derived from
|
||||
address token;
|
||||
PledgeState pledgeState; // Pledged, Paying, Paid
|
||||
}
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ contract Pledges is AragonApp, LiquidPledgingStorage {
|
|||
uint64 intendedProject,
|
||||
uint64 commitTime,
|
||||
uint64 oldPledge,
|
||||
address token,
|
||||
PledgeState pledgeState
|
||||
) {
|
||||
Pledge memory p = _findPledge(idPledge);
|
||||
|
@ -61,6 +62,7 @@ contract Pledges is AragonApp, LiquidPledgingStorage {
|
|||
intendedProject = p.intendedProject;
|
||||
commitTime = p.commitTime;
|
||||
oldPledge = p.oldPledge;
|
||||
token = p.token;
|
||||
pledgeState = p.pledgeState;
|
||||
}
|
||||
|
||||
|
@ -91,10 +93,11 @@ contract Pledges is AragonApp, LiquidPledgingStorage {
|
|||
uint64 intendedProject,
|
||||
uint64 commitTime,
|
||||
uint64 oldPledge,
|
||||
address token,
|
||||
PledgeState state
|
||||
) internal returns (uint64)
|
||||
{
|
||||
bytes32 hPledge = keccak256(delegationChain, owner, intendedProject, commitTime, oldPledge, state);
|
||||
bytes32 hPledge = keccak256(delegationChain, owner, intendedProject, commitTime, oldPledge, token, state);
|
||||
uint64 id = hPledge2idx[hPledge];
|
||||
if (id > 0) {
|
||||
return id;
|
||||
|
@ -110,6 +113,7 @@ contract Pledges is AragonApp, LiquidPledgingStorage {
|
|||
intendedProject,
|
||||
commitTime,
|
||||
oldPledge,
|
||||
token,
|
||||
state
|
||||
)
|
||||
);
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
pragma solidity ^0.4.18;
|
||||
|
||||
/**
|
||||
* WARNING: This token is for testing purposes only
|
||||
* and has been modified from the original version: https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/token/ERC20/StandardToken.sol
|
||||
*
|
||||
* @title Standard ERC20 token
|
||||
*
|
||||
* @dev Implementation of the basic standard token.
|
||||
* @dev https://github.com/ethereum/EIPs/issues/20
|
||||
* @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
|
||||
*/
|
||||
contract StandardToken {
|
||||
|
||||
event Transfer(address indexed from, address indexed to, uint256 value);
|
||||
event Approval(address indexed owner, address indexed spender, uint256 value);
|
||||
|
||||
mapping (address => mapping (address => uint256)) internal allowed;
|
||||
mapping(address => uint256) balances;
|
||||
|
||||
uint256 totalSupply_;
|
||||
address owner;
|
||||
|
||||
function StandardToken() public {
|
||||
owner = msg.sender;
|
||||
}
|
||||
|
||||
modifier onlyOwner() {
|
||||
require(msg.sender == owner);
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev total number of tokens in existence
|
||||
*/
|
||||
function totalSupply() public view returns (uint256) {
|
||||
return totalSupply_;
|
||||
}
|
||||
|
||||
function mint(address _to, uint _value) public onlyOwner {
|
||||
totalSupply_ += _value;
|
||||
balances[_to] += _value;
|
||||
Transfer(0, _to, _value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev transfer token for a specified address
|
||||
* @param _to The address to transfer to.
|
||||
* @param _value The amount to be transferred.
|
||||
*/
|
||||
function transfer(address _to, uint256 _value) public returns (bool) {
|
||||
require(_to != address(0));
|
||||
require(_value <= balances[msg.sender]);
|
||||
|
||||
// SafeMath.sub will throw if there is not enough balance.
|
||||
balances[msg.sender] = balances[msg.sender] - _value;
|
||||
balances[_to] = balances[_to] + _value;
|
||||
Transfer(msg.sender, _to, _value);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Gets the balance of the specified address.
|
||||
* @param _owner The address to query the the balance of.
|
||||
* @return An uint256 representing the amount owned by the passed address.
|
||||
*/
|
||||
function balanceOf(address _owner) public view returns (uint256 balance) {
|
||||
return balances[_owner];
|
||||
}
|
||||
/**
|
||||
* @dev Transfer tokens from one address to another
|
||||
* @param _from address The address which you want to send tokens from
|
||||
* @param _to address The address which you want to transfer to
|
||||
* @param _value uint256 the amount of tokens to be transferred
|
||||
*/
|
||||
function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
|
||||
require(_to != address(0));
|
||||
require(_value <= balances[_from]);
|
||||
require(_value <= allowed[_from][msg.sender]);
|
||||
|
||||
balances[_from] = balances[_from] - _value;
|
||||
balances[_to] = balances[_to] + _value;
|
||||
allowed[_from][msg.sender] = allowed[_from][msg.sender] - _value;
|
||||
Transfer(_from, _to, _value);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
|
||||
*
|
||||
* Beware that changing an allowance with this method brings the risk that someone may use both the old
|
||||
* and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
|
||||
* race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
|
||||
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
|
||||
* @param _spender The address which will spend the funds.
|
||||
* @param _value The amount of tokens to be spent.
|
||||
*/
|
||||
function approve(address _spender, uint256 _value) public returns (bool) {
|
||||
allowed[msg.sender][_spender] = _value;
|
||||
Approval(msg.sender, _spender, _value);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Function to check the amount of tokens that an owner allowed to a spender.
|
||||
* @param _owner address The address which owns the funds.
|
||||
* @param _spender address The address which will spend the funds.
|
||||
* @return A uint256 specifying the amount of tokens still available for the spender.
|
||||
*/
|
||||
function allowance(address _owner, address _spender) public view returns (uint256) {
|
||||
return allowed[_owner][_spender];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Increase the amount of tokens that an owner allowed to a spender.
|
||||
*
|
||||
* approve should be called when allowed[_spender] == 0. To increment
|
||||
* allowed value is better to use this function to avoid 2 calls (and wait until
|
||||
* the first transaction is mined)
|
||||
* From MonolithDAO Token.sol
|
||||
* @param _spender The address which will spend the funds.
|
||||
* @param _addedValue The amount of tokens to increase the allowance by.
|
||||
*/
|
||||
function increaseApproval(address _spender, uint _addedValue) public returns (bool) {
|
||||
allowed[msg.sender][_spender] = allowed[msg.sender][_spender] + _addedValue;
|
||||
Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Decrease the amount of tokens that an owner allowed to a spender.
|
||||
*
|
||||
* approve should be called when allowed[_spender] == 0. To decrement
|
||||
* allowed value is better to use this function to avoid 2 calls (and wait until
|
||||
* the first transaction is mined)
|
||||
* From MonolithDAO Token.sol
|
||||
* @param _spender The address which will spend the funds.
|
||||
* @param _subtractedValue The amount of tokens to decrease the allowance by.
|
||||
*/
|
||||
function decreaseApproval(address _spender, uint _subtractedValue) public returns (bool) {
|
||||
uint oldValue = allowed[msg.sender][_spender];
|
||||
if (_subtractedValue > oldValue) {
|
||||
allowed[msg.sender][_spender] = 0;
|
||||
} else {
|
||||
allowed[msg.sender][_spender] = oldValue - _subtractedValue;
|
||||
}
|
||||
Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -12,6 +12,7 @@ class LiquidPledgingState {
|
|||
.then((res) => {
|
||||
pledge.amount = res.amount;
|
||||
pledge.owner = res.owner;
|
||||
pledge.token = res.token;
|
||||
|
||||
if (res.intendedProject) {
|
||||
pledge.intendedProject = res.intendedProject;
|
||||
|
@ -68,12 +69,11 @@ class LiquidPledgingState {
|
|||
admin.name = res.name;
|
||||
admin.url = res.url;
|
||||
admin.commitTime = res.commitTime;
|
||||
if (admin.adminType === 'Project') {
|
||||
if (admin.type === 'Project') {
|
||||
admin.parentProject = res.parentProject;
|
||||
admin.canceled = res.canceled;
|
||||
}
|
||||
admin.plugin = res.plugin;
|
||||
admin.canceled = res.canceled;
|
||||
return admin;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
},
|
||||
"scripts": {
|
||||
"test": "npm run build; mocha --harmony",
|
||||
"sol-compile": "solcpiler -i './contracts/+(LPVault|LPFactory|LiquidPledging|LiquidPledgingMock|TestSimpleProjectPlugin|TestSimpleProjectPluginFactory).sol' --solc-version v0.4.18+commit.9cf6e910",
|
||||
"sol-compile": "solcpiler -i './contracts/{LPVault,LPFactory,LiquidPledging,LiquidPledgingMock,test/{TestSimpleProjectPluginFactory,StandardToken}}.sol' --solc-version v0.4.18+commit.9cf6e910",
|
||||
"js-compile": "babel -d lib/ js/",
|
||||
"build": "npm run sol-compile; npm run js-compile",
|
||||
"prepublish": "npm run build"
|
||||
|
|
|
@ -29,6 +29,7 @@ describe('LiquidPledging plugins test', function () {
|
|||
let giver1;
|
||||
let adminProject1;
|
||||
let adminDelegate1;
|
||||
let token;
|
||||
|
||||
before(async () => {
|
||||
testrpc = TestRPC.server({
|
||||
|
@ -64,6 +65,10 @@ describe('LiquidPledging plugins test', function () {
|
|||
liquidPledging = new contracts.LiquidPledgingMock(web3, lpAddress);
|
||||
|
||||
liquidPledgingState = new LiquidPledgingState(liquidPledging);
|
||||
|
||||
token = await contracts.StandardToken.new(web3);
|
||||
await token.mint(giver1, web3.utils.toWei('1000'));
|
||||
await token.approve(liquidPledging.$address, "0xFFFFFFFFFFFFFFFF", { from: giver1 });
|
||||
});
|
||||
|
||||
it('Should create create giver with no plugin', async function () {
|
||||
|
|
|
@ -26,6 +26,7 @@ describe('LiquidPledging cancelPledge normal scenario', function () {
|
|||
let giver1;
|
||||
let adminProject1;
|
||||
let adminProject2;
|
||||
let token;
|
||||
|
||||
before(async () => {
|
||||
testrpc = TestRPC.server({
|
||||
|
@ -61,11 +62,15 @@ describe('LiquidPledging cancelPledge normal scenario', function () {
|
|||
liquidPledging = new contracts.LiquidPledgingMock(web3, lpAddress);
|
||||
|
||||
liquidPledgingState = new LiquidPledgingState(liquidPledging);
|
||||
|
||||
token = await contracts.StandardToken.new(web3);
|
||||
await token.mint(giver1, web3.utils.toWei('1000'));
|
||||
await token.approve(liquidPledging.$address, "0xFFFFFFFFFFFFFFFF", { from: giver1 });
|
||||
});
|
||||
|
||||
it('Should add project and donate ', async () => {
|
||||
await liquidPledging.addProject('Project1', 'URLProject1', adminProject1, 0, 0, '0x0', { from: adminProject1 });
|
||||
await liquidPledging.addGiverAndDonate(1, { from: giver1, value: '1000' });
|
||||
await liquidPledging.addGiverAndDonate(1, token.$address, 1000, { from: giver1 });
|
||||
|
||||
const nAdmins = await liquidPledging.numberOfPledgeAdmins();
|
||||
assert.equal(nAdmins, 2);
|
||||
|
|
|
@ -29,6 +29,7 @@ describe('DelegationChain test', function () {
|
|||
let delegate2;
|
||||
let delegate3;
|
||||
let adminProject1;
|
||||
let token;
|
||||
|
||||
const gasUsage = {};
|
||||
before(async () => {
|
||||
|
@ -68,6 +69,10 @@ describe('DelegationChain test', function () {
|
|||
liquidPledging = new contracts.LiquidPledgingMock(web3, lpAddress);
|
||||
|
||||
liquidPledgingState = new LiquidPledgingState(liquidPledging);
|
||||
|
||||
token = await contracts.StandardToken.new(web3);
|
||||
await token.mint(giver1, web3.utils.toWei('1000'));
|
||||
await token.approve(liquidPledging.$address, "0xFFFFFFFFFFFFFFFF", { from: giver1 });
|
||||
});
|
||||
|
||||
it('Should add pledgeAdmins', async () => {
|
||||
|
@ -83,7 +88,7 @@ describe('DelegationChain test', function () {
|
|||
});
|
||||
|
||||
it('Should allow previous delegate to transfer pledge', async () => {
|
||||
await liquidPledging.donate(1, 2, { from: giver1, value: 1000 });
|
||||
await liquidPledging.donate(1, 2, token.$address, 1000, { from: giver1 });
|
||||
// add delegate2 to chain
|
||||
await liquidPledging.transfer(2, 2, 1000, 3, { from: delegate1 });
|
||||
// delegate 1 transfer pledge back to self, thus undelegating delegate2
|
||||
|
|
|
@ -36,6 +36,8 @@ describe('LiquidPledging test', function () {
|
|||
let escapeHatchDestination;
|
||||
let escapeHatchCaller;
|
||||
let acl;
|
||||
let giver1Token;
|
||||
let giver2Token;
|
||||
|
||||
before(async () => {
|
||||
testrpc = TestRPC.server({
|
||||
|
@ -86,6 +88,15 @@ describe('LiquidPledging test', function () {
|
|||
await acl.createPermission(accounts[0], vault.$address, await vault.CONFIRM_PAYMENT_ROLE(), accounts[0], {$extraGas: 200000});
|
||||
await acl.grantPermission(escapeHatchCaller, vault.$address, await vault.ESCAPE_HATCH_CALLER_ROLE(), {$extraGas: 200000});
|
||||
await acl.revokePermission(accounts[0], vault.$address, await vault.ESCAPE_HATCH_CALLER_ROLE(), {$extraGas: 200000});
|
||||
|
||||
giver1Token = await contracts.StandardToken.new(web3);
|
||||
giver2Token = await contracts.StandardToken.new(web3);
|
||||
|
||||
await giver1Token.mint(giver1, web3.utils.toWei('1000'));
|
||||
await giver2Token.mint(giver2, web3.utils.toWei('1000'));
|
||||
|
||||
await giver1Token.approve(liquidPledging.$address, "0xFFFFFFFFFFFFFFFF", {from: giver1});
|
||||
await giver2Token.approve(liquidPledging.$address, "0xFFFFFFFFFFFFFFFF", {from: giver2});
|
||||
});
|
||||
it('Should create a giver', async () => {
|
||||
await liquidPledging.addGiver('Giver1', 'URLGiver1', 86400, 0, { from: giver1, gas: 1000000 });
|
||||
|
@ -99,12 +110,16 @@ describe('LiquidPledging test', function () {
|
|||
assert.equal(res[4], 86400);
|
||||
});
|
||||
it('Should make a donation', async () => {
|
||||
const r = await liquidPledging.donate(1, 1, { from: giver1, value: utils.toWei('1'), gas: 1000000 });
|
||||
const r = await liquidPledging.donate(1, 1, giver1Token.$address, utils.toWei('1'), { from: giver1, $extraGas: 100000 });
|
||||
const nPledges = await liquidPledging.numberOfPledges();
|
||||
assert.equal(nPledges, 1);
|
||||
const p = await liquidPledging.getPledge(1);
|
||||
assert.equal(p.amount, utils.toWei('1'));
|
||||
assert.equal(p.owner, 1);
|
||||
const vaultBal = await giver1Token.balanceOf(vault.$address);
|
||||
const giver1Bal = await giver1Token.balanceOf(giver1);
|
||||
assert.equal(vaultBal, web3.utils.toWei('1'))
|
||||
assert.equal(giver1Bal, web3.utils.toWei('999'))
|
||||
});
|
||||
it('Should create a delegate', async () => {
|
||||
await liquidPledging.addDelegate('Delegate1', 'URLDelegate1', 0, 0, { from: delegate1 });
|
||||
|
@ -165,27 +180,29 @@ describe('LiquidPledging test', function () {
|
|||
const nPledges = await liquidPledging.numberOfPledges();
|
||||
assert.equal(nPledges, 3);
|
||||
const res3 = await liquidPledging.getPledge(3);
|
||||
assert.equal(res3[0], utils.toWei('0.2'));
|
||||
assert.equal(res3[1], 1); // Owner
|
||||
assert.equal(res3[2], 1); // Delegates
|
||||
assert.equal(res3[3], 3); // Proposed Project
|
||||
assert.isAbove(utils.toDecimal(res3[4]), n + 86000);
|
||||
assert.equal(res3[5], 0); // Old Node
|
||||
assert.equal(res3[6], 0); // Not Paid
|
||||
assert.equal(res3.amount, utils.toWei('0.2'));
|
||||
assert.equal(res3.owner, 1);
|
||||
assert.equal(res3.nDelegates, 1);
|
||||
assert.equal(res3.intendedProject, 3);
|
||||
assert.isAbove(utils.toDecimal(res3.commitTime), n + 86000);
|
||||
assert.equal(res3.oldPledge, 0);
|
||||
assert.equal(res3.token, giver1Token.$address);
|
||||
assert.equal(res3.pledgeState, 0); // Not Paid
|
||||
});
|
||||
it('Giver should change his mind and assign half of it to project2', async () => {
|
||||
await liquidPledging.transfer(1, 3, utils.toWei('0.1'), 4, { from: giver1 });
|
||||
const nPledges = await liquidPledging.numberOfPledges();
|
||||
assert.equal(nPledges, 4);
|
||||
const res3 = await liquidPledging.getPledge(3);
|
||||
assert.equal(res3[0], utils.toWei('0.1'));
|
||||
assert.equal(res3.amount, utils.toWei('0.1'));
|
||||
const res4 = await liquidPledging.getPledge(4);
|
||||
assert.equal(res4[1], 4); // Owner
|
||||
assert.equal(res4[2], 0); // Delegates
|
||||
assert.equal(res4[3], 0); // Proposed Project
|
||||
assert.equal(res4[4], 0);
|
||||
assert.equal(res4[5], 2); // Old Node
|
||||
assert.equal(res4[6], 0); // Not Paid
|
||||
assert.equal(res4.owner, 4);
|
||||
assert.equal(res4.nDelegates, 0);
|
||||
assert.equal(res4.intendedProject, 0);
|
||||
assert.equal(res4.commitTime, 0);
|
||||
assert.equal(res4.oldPledge, 2);
|
||||
assert.equal(res4.token, giver1Token.$address);
|
||||
assert.equal(res4.pledgeState, 0); // Not Paid
|
||||
});
|
||||
it('After the time, the project1 should be able to spend part of it', async () => {
|
||||
const n = Math.floor(new Date().getTime() / 1000);
|
||||
|
@ -194,27 +211,29 @@ describe('LiquidPledging test', function () {
|
|||
const nPledges = await liquidPledging.numberOfPledges();
|
||||
assert.equal(nPledges, 6);
|
||||
const res5 = await liquidPledging.getPledge(5);
|
||||
assert.equal(res5[0], utils.toWei('0.05'));
|
||||
assert.equal(res5[1], 3); // Owner
|
||||
assert.equal(res5[2], 0); // Delegates
|
||||
assert.equal(res5[3], 0); // Proposed Project
|
||||
assert.equal(res5[4], 0); // commit time
|
||||
assert.equal(res5[5], 2); // Old Node
|
||||
assert.equal(res5[6], 0); // Not Paid
|
||||
assert.equal(res5.amount, utils.toWei('0.05'));
|
||||
assert.equal(res5.owner, 3);
|
||||
assert.equal(res5.nDelegates, 0);
|
||||
assert.equal(res5.intendedProject, 0);
|
||||
assert.equal(res5.commitTime, 0);
|
||||
assert.equal(res5.oldPledge, 2);
|
||||
assert.equal(res5.token, giver1Token.$address);
|
||||
assert.equal(res5.pledgeState, 0); // Not Paid
|
||||
const res6 = await liquidPledging.getPledge(6);
|
||||
assert.equal(res6[0], utils.toWei('0.05'));
|
||||
assert.equal(res6[1], 3); // Owner
|
||||
assert.equal(res6[2], 0); // Delegates
|
||||
assert.equal(res6[3], 0); // Proposed Project
|
||||
assert.equal(res6[4], 0); // commit time
|
||||
assert.equal(res6[5], 2); // Old Node
|
||||
assert.equal(res6[6], 1); // Peinding paid Paid
|
||||
assert.equal(res6.amount, utils.toWei('0.05'));
|
||||
assert.equal(res6.owner, 3);
|
||||
assert.equal(res6.nDelegates, 0);
|
||||
assert.equal(res6.intendedProject, 0);
|
||||
assert.equal(res6.commitTime, 0);
|
||||
assert.equal(res6.oldPledge, 2);
|
||||
assert.equal(res6.token, giver1Token.$address);
|
||||
assert.equal(res6.pledgeState, 1); // Pending
|
||||
});
|
||||
it('Should collect the Ether', async () => {
|
||||
const initialBalance = await web3.eth.getBalance(adminProject1);
|
||||
it('Should collect the token', async () => {
|
||||
const initialBalance = await giver1Token.balanceOf(adminProject1);
|
||||
|
||||
await vault.confirmPayment(0, {$extraGas: 200000});
|
||||
const finalBalance = await web3.eth.getBalance(adminProject1);
|
||||
const finalBalance = await giver1Token.balanceOf(adminProject1);
|
||||
|
||||
const collected = utils.fromWei(utils.toBN(finalBalance).sub(utils.toBN(initialBalance)));
|
||||
|
||||
|
@ -223,13 +242,14 @@ describe('LiquidPledging test', function () {
|
|||
const nPledges = await liquidPledging.numberOfPledges();
|
||||
assert.equal(nPledges, 7);
|
||||
const res7 = await liquidPledging.getPledge(7);
|
||||
assert.equal(res7[0], utils.toWei('0.05'));
|
||||
assert.equal(res7[1], 3); // Owner
|
||||
assert.equal(res7[2], 0); // Delegates
|
||||
assert.equal(res7[3], 0); // Proposed Project
|
||||
assert.equal(res7[4], 0); // commit time
|
||||
assert.equal(res7[5], 2); // Old pledge
|
||||
assert.equal(res7[6], 2); // Peinding paid Paid
|
||||
assert.equal(res7.amount, utils.toWei('0.05'));
|
||||
assert.equal(res7.owner, 3);
|
||||
assert.equal(res7.nDelegates, 0);
|
||||
assert.equal(res7.intendedProject, 0);
|
||||
assert.equal(res7.commitTime, 0);
|
||||
assert.equal(res7.oldPledge, 2);
|
||||
assert.equal(res7.token, giver1Token.$address);
|
||||
assert.equal(res7.pledgeState, 2); // Pending
|
||||
});
|
||||
it('Admin of the project1 should be able to cancel project1', async () => {
|
||||
await liquidPledging.cancelProject(3, { from: adminProject1, $extraGas: 100000 });
|
||||
|
@ -243,7 +263,7 @@ describe('LiquidPledging test', function () {
|
|||
await assertFail(
|
||||
liquidPledging.withdraw(5, utils.toWei('0.01'), { from: adminProject1, gas: 4000000 })
|
||||
);
|
||||
});
|
||||
});
|
||||
it('Delegate should send part of this ETH to project2', async () => {
|
||||
await liquidPledging.transfer(2, 5, utils.toWei('0.03'), 4, {from: delegate1, $extraGas: 100000});
|
||||
const st = await liquidPledgingState.getState(liquidPledging);
|
||||
|
@ -324,10 +344,10 @@ describe('LiquidPledging test', function () {
|
|||
|
||||
await liquidPledging.mWithdraw(encodedPledges, { from: giver1, $extraGas: 200000 });
|
||||
|
||||
const initialBalance = await web3.eth.getBalance(giver1);
|
||||
const initialBalance = await giver1Token.balanceOf(giver1);
|
||||
await vault.multiConfirm([2, 3, 4, 5, 6], {$extraGas: 200000});
|
||||
|
||||
const finalBalance = await web3.eth.getBalance(giver1);
|
||||
const finalBalance = await giver1Token.balanceOf(giver1);
|
||||
const collected = utils.fromWei(utils.toBN(finalBalance).sub(utils.toBN(initialBalance)));
|
||||
|
||||
assert.equal(collected, 0.95);
|
||||
|
@ -335,9 +355,9 @@ describe('LiquidPledging test', function () {
|
|||
it('Should make a donation and create giver', async () => {
|
||||
const oldNPledges = await liquidPledging.numberOfPledges();
|
||||
const oldNAdmins = await liquidPledging.numberOfPledgeAdmins();
|
||||
await liquidPledging.addGiverAndDonate(1, { from: giver2, value: utils.toWei('1'), $extraGas: 200000 });
|
||||
await liquidPledging.addGiverAndDonate(1, giver2Token.$address, utils.toWei('1'), { from: giver2, $extraGas: 200000 });
|
||||
const nPledges = await liquidPledging.numberOfPledges();
|
||||
assert.equal(utils.toDecimal(nPledges), utils.toDecimal(oldNPledges) + 1);
|
||||
assert.equal(utils.toDecimal(nPledges), utils.toDecimal(oldNPledges) + 2);
|
||||
const nAdmins = await liquidPledging.numberOfPledgeAdmins();
|
||||
assert.equal(utils.toDecimal(nAdmins), utils.toDecimal(oldNAdmins) + 1);
|
||||
const res = await liquidPledging.getPledgeAdmin(nAdmins);
|
||||
|
@ -346,6 +366,8 @@ describe('LiquidPledging test', function () {
|
|||
assert.equal(res[2], '');
|
||||
assert.equal(res[3], '');
|
||||
assert.equal(res[4], 259200); // default to 3 day commitTime
|
||||
const giver2Bal = await giver2Token.balanceOf(giver2);
|
||||
assert.equal(giver2Bal, utils.toWei('999'));
|
||||
});
|
||||
it('Should allow childProject with different parentProject owner', async () => {
|
||||
const nAdminsBefore = await liquidPledging.numberOfPledgeAdmins();
|
||||
|
|
|
@ -28,6 +28,7 @@ describe('NormalizePledge test', function () {
|
|||
let delegate2;
|
||||
let adminProject1;
|
||||
let adminProject2;
|
||||
let token;
|
||||
|
||||
before(async () => {
|
||||
testrpc = TestRPC.server({
|
||||
|
@ -66,6 +67,12 @@ describe('NormalizePledge test', function () {
|
|||
liquidPledging = new contracts.LiquidPledgingMock(web3, lpAddress);
|
||||
|
||||
liquidPledgingState = new LiquidPledgingState(liquidPledging);
|
||||
|
||||
token = await contracts.StandardToken.new(web3);
|
||||
await token.mint(giver1, web3.utils.toWei('1000'));
|
||||
await token.mint(giver2, web3.utils.toWei('1000'));
|
||||
await token.approve(liquidPledging.$address, "0xFFFFFFFFFFFFFFFF", { from: giver1 });
|
||||
await token.approve(liquidPledging.$address, "0xFFFFFFFFFFFFFFFF", { from: giver2 });
|
||||
});
|
||||
|
||||
it('Should add pledgeAdmins', async () => {
|
||||
|
@ -82,11 +89,11 @@ describe('NormalizePledge test', function () {
|
|||
|
||||
it('Should commit pledges if commitTime has passed', async () => {
|
||||
// commitTime 259200
|
||||
await liquidPledging.donate(1, 2, { from: giver1, value: 1000 });
|
||||
await liquidPledging.donate(1, 2, token.$address, 1000, { from: giver1 });
|
||||
// commitTime 86400
|
||||
await liquidPledging.donate(1, 3, { from: giver1, value: 1000 });
|
||||
await liquidPledging.donate(1, 3, token.$address, 1000, { from: giver1 });
|
||||
// commitTime 0
|
||||
await liquidPledging.donate(6, 3, { from: giver2, value: 1000 });
|
||||
await liquidPledging.donate(6, 3, token.$address, 1000, { from: giver2 });
|
||||
|
||||
// set the time
|
||||
const now = Math.floor(new Date().getTime() / 1000);
|
||||
|
|
|
@ -24,6 +24,7 @@ describe('Vault test', function () {
|
|||
let giver1;
|
||||
let adminProject1;
|
||||
let restrictedPaymentsConfirmer;
|
||||
let token;
|
||||
|
||||
before(async () => {
|
||||
testrpc = TestRPC.server({
|
||||
|
@ -76,12 +77,16 @@ describe('Vault test', function () {
|
|||
|
||||
const nAdmins = await liquidPledging.numberOfPledgeAdmins();
|
||||
assert.equal(nAdmins, 2);
|
||||
|
||||
token = await contracts.StandardToken.new(web3);
|
||||
await token.mint(giver1, web3.utils.toWei('1000'));
|
||||
await token.approve(liquidPledging.$address, "0xFFFFFFFFFFFFFFFF", {from: giver1});
|
||||
});
|
||||
|
||||
it('Should hold funds from liquidPledging', async function () {
|
||||
await liquidPledging.addGiverAndDonate(2, { from: giver1, value: 10000, $extraGas: 100000 });
|
||||
await liquidPledging.addGiverAndDonate(2, token.$address, 10000, { from: giver1, $extraGas: 100000 });
|
||||
|
||||
const balance = await web3.eth.getBalance(vault.$address);
|
||||
const balance = await token.balanceOf(vault.$address);
|
||||
assert.equal(10000, balance);
|
||||
});
|
||||
|
||||
|
@ -94,19 +99,21 @@ describe('Vault test', function () {
|
|||
});
|
||||
|
||||
it('escapeFunds should send funds to escapeHatchDestination', async function () {
|
||||
const preBalance = await web3.eth.getBalance(escapeHatchDestination);
|
||||
const preBalance = await token.balanceOf(escapeHatchDestination);
|
||||
|
||||
await vault.escapeFunds(0x0, 1000, { from: escapeHatchCaller, $extraGas: 200000 });
|
||||
assertFail(vault.escapeFunds(0x0, 1000, { from: escapeHatchCaller, gas: 1000000}));
|
||||
|
||||
const vaultBalance = await web3.eth.getBalance(vault.$address);
|
||||
await vault.escapeFunds(token.$address, 1000, { from: escapeHatchCaller, $extraGas: 200000 });
|
||||
|
||||
const vaultBalance = await token.balanceOf(vault.$address);
|
||||
assert.equal(9000, vaultBalance);
|
||||
|
||||
const expected = web3.utils.toBN(preBalance).add(web3.utils.toBN('1000')).toString();
|
||||
const postBalance = await web3.eth.getBalance(escapeHatchDestination);
|
||||
const postBalance = await token.balanceOf(escapeHatchDestination);
|
||||
|
||||
assert.equal(expected, postBalance);
|
||||
|
||||
await web3.eth.sendTransaction({from: escapeHatchCaller, to: vault.$address, value: '1000', gas: 21000});
|
||||
await token.transfer(vault.$address, 1000, {from: escapeHatchDestination, $extraGas: 200000});
|
||||
});
|
||||
|
||||
it('should restrict confirm payment to payments under specified amount', async function () {
|
||||
|
|
Loading…
Reference in New Issue