feat: add test for funding escrows
This commit is contained in:
parent
8bd558f677
commit
01dee410f6
|
@ -0,0 +1,260 @@
|
|||
/*global contract, config, it, embark, web3, before, describe, beforeEach*/
|
||||
const TestUtils = require("../utils/testUtils");
|
||||
|
||||
const License = embark.require('Embark/contracts/License');
|
||||
const MetadataStore = embark.require('Embark/contracts/MetadataStore');
|
||||
const Escrow = embark.require('Embark/contracts/Escrow');
|
||||
const StandardToken = embark.require('Embark/contracts/StandardToken');
|
||||
const SNT = embark.require('Embark/contracts/SNT');
|
||||
|
||||
const FIAT = 0;
|
||||
|
||||
let accounts;
|
||||
const feeAmount = 10;
|
||||
const fundAmount = 100;
|
||||
|
||||
config({
|
||||
deployment: {
|
||||
// The order here corresponds to the order of `web3.eth.getAccounts`, so the first one is the `defaultAccount`
|
||||
},
|
||||
contracts: {
|
||||
"MiniMeToken": { "deploy": false },
|
||||
"MiniMeTokenFactory": {
|
||||
|
||||
},
|
||||
"SNT": {
|
||||
"instanceOf": "MiniMeToken",
|
||||
"args": [
|
||||
"$MiniMeTokenFactory",
|
||||
"0x0000000000000000000000000000000000000000",
|
||||
0,
|
||||
"TestMiniMeToken",
|
||||
18,
|
||||
"STT",
|
||||
true
|
||||
]
|
||||
},
|
||||
License: {
|
||||
args: ["$SNT", TestUtils.zeroAddress, 10, 86400 * 365]
|
||||
},
|
||||
MetadataStore: {
|
||||
args: ["$License"]
|
||||
},
|
||||
Escrow: {
|
||||
args: ["$License", "$accounts[5]", "$MetadataStore", "$SNT", "0x0000000000000000000000000000000000000001", feeAmount]
|
||||
},
|
||||
StandardToken: {
|
||||
}
|
||||
}
|
||||
}, (_err, web3_accounts) => {
|
||||
accounts = web3_accounts;
|
||||
});
|
||||
|
||||
function sequentialPromiseExec(tasks) {
|
||||
return tasks.reduce((p, task) => p.then(task), Promise.resolve());
|
||||
}
|
||||
|
||||
contract("Escrow Funding", function() {
|
||||
const {toBN} = web3.utils;
|
||||
const value = web3.utils.toWei("0.1", "ether");
|
||||
|
||||
let expirationTime = parseInt((new Date()).getTime() / 1000, 10) + 1000;
|
||||
|
||||
let receipt, escrowId, ethOfferId, tokenOfferId, SNTOfferId;
|
||||
|
||||
this.timeout(0);
|
||||
|
||||
before(async () => {
|
||||
await StandardToken.methods.mint(accounts[0], 100000000).send();
|
||||
await SNT.methods.generateTokens(accounts[0], 100000000).send();
|
||||
const encodedCall = License.methods.buy().encodeABI();
|
||||
await SNT.methods.approveAndCall(License.options.address, 10, encodedCall).send({from: accounts[0]});
|
||||
|
||||
receipt = await MetadataStore.methods.addOffer(TestUtils.zeroAddress, License.address, "London", "USD", "Iuri", [0], 0, 1).send({from: accounts[0]});
|
||||
ethOfferId = receipt.events.OfferAdded.returnValues.offerId;
|
||||
|
||||
receipt = await MetadataStore.methods.addOffer(StandardToken.options.address, License.address, "London", "USD", "Iuri", [0], 0, 1).send({from: accounts[0]});
|
||||
tokenOfferId = receipt.events.OfferAdded.returnValues.offerId;
|
||||
|
||||
receipt = await MetadataStore.methods.addOffer(SNT.options.address, License.address, "London", "USD", "Iuri", [0], 0, 1).send({from: accounts[0]});
|
||||
SNTOfferId = receipt.events.OfferAdded.returnValues.offerId;
|
||||
});
|
||||
|
||||
describe("ETH as asset", async () => {
|
||||
beforeEach(async () => {
|
||||
receipt = await Escrow.methods.create(accounts[1], ethOfferId, 123, FIAT, [0], "0x00", "U", "12345")
|
||||
.send({from: accounts[0]});
|
||||
|
||||
escrowId = receipt.events.Created.returnValues.escrowId;
|
||||
});
|
||||
|
||||
it("Should fund escrow and deduct an SNT fee", async () => {
|
||||
// Still requires 2 transactions, because approveAndCall cannot send ETH
|
||||
// TODO: test if inside the contract we can encode the call, and call approveAndCall
|
||||
|
||||
await SNT.methods.approve(Escrow.options.address, feeAmount).send({from: accounts[0]});
|
||||
|
||||
receipt = await Escrow.methods.fund(escrowId, value, expirationTime)
|
||||
.send({from: accounts[0], value});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
describe("Tokens as Asset", async () => {
|
||||
let escrowIdSNT, escrowIdToken;
|
||||
|
||||
beforeEach(async () => {
|
||||
// Reset allowance
|
||||
await SNT.methods.approve(Escrow.options.address, "0").send({from: accounts[0]});
|
||||
await StandardToken.methods.approve(Escrow.options.address, "0").send({from: accounts[0]});
|
||||
|
||||
receipt = await Escrow.methods.create(accounts[1], SNTOfferId, 123, FIAT, [0], "0x00", "U", "12345")
|
||||
.send({from: accounts[0]});
|
||||
escrowIdSNT = receipt.events.Created.returnValues.escrowId;
|
||||
|
||||
receipt = await Escrow.methods.create(accounts[1], tokenOfferId, 123, FIAT, [0], "0x00", "U", "12345")
|
||||
.send({from: accounts[0]});
|
||||
escrowIdToken = receipt.events.Created.returnValues.escrowId;
|
||||
});
|
||||
|
||||
const execute = async (token, escrowId) => {
|
||||
const {approvalPromises, trxToSend} = await tokenApprovalAndBuildTrx(token, escrowId);
|
||||
await sequentialPromiseExec(approvalPromises);
|
||||
await trxToSend.send({from: accounts[0]});
|
||||
};
|
||||
|
||||
it("Allowance == to funds and fee. Token is SNT", async () => {
|
||||
const amount = toBN(feeAmount).add(toBN(fundAmount)).toString(10);
|
||||
await SNT.methods.approve(Escrow.options.address, amount).send({from: accounts[0]});
|
||||
|
||||
await execute(SNT, escrowIdSNT);
|
||||
});
|
||||
|
||||
it("Allowance > to funds and fee. Token is SNT", async () => {
|
||||
const amount = toBN(feeAmount).add(toBN(fundAmount)).add(toBN(100)).toString(10);
|
||||
await SNT.methods.approve(Escrow.options.address, amount).send({from: accounts[0]});
|
||||
|
||||
await execute(SNT, escrowIdSNT);
|
||||
});
|
||||
|
||||
it("Allowance < than funds and fee. Token is SNT", async () => {
|
||||
const amount = toBN(feeAmount).add(toBN(fundAmount)).sub(toBN(10)).toString(10);
|
||||
await SNT.methods.approve(Escrow.options.address, amount).send({from: accounts[0]});
|
||||
|
||||
await execute(SNT, escrowIdSNT);
|
||||
});
|
||||
|
||||
it("Allowance == to required funds. Token is not SNT. SNT Allowance == required Fees", async () => {
|
||||
await StandardToken.methods.approve(Escrow.options.address, fundAmount).send({from: accounts[0]});
|
||||
|
||||
await execute(StandardToken, escrowIdToken);
|
||||
});
|
||||
|
||||
it("Allowance > to required funds. Token is not SNT. SNT Allowance == required Fees", async () => {
|
||||
const amount = toBN(feeAmount).add(toBN(fundAmount)).add(toBN(100)).toString(10);
|
||||
await StandardToken.methods.approve(Escrow.options.address, amount).send({from: accounts[0]});
|
||||
|
||||
await execute(StandardToken, escrowIdToken);
|
||||
});
|
||||
|
||||
it("Allowance < to required funds. Token is not SNT. SNT Allowance == required Fees", async () => {
|
||||
const amount = toBN(fundAmount).sub(toBN(10)).toString(10);
|
||||
await StandardToken.methods.approve(Escrow.options.address, amount).send({from: accounts[0]});
|
||||
|
||||
await execute(StandardToken, escrowIdToken);
|
||||
});
|
||||
|
||||
it("Allowance == to required funds. Token is not SNT. SNT Allowance > required Fees", async () => {
|
||||
await StandardToken.methods.approve(Escrow.options.address, fundAmount).send({from: accounts[0]});
|
||||
await SNT.methods.approve(Escrow.options.address, 1000).send({from: accounts[0]});
|
||||
|
||||
await execute(StandardToken, escrowIdToken);
|
||||
});
|
||||
|
||||
it("Allowance > to required funds. Token is not SNT. SNT Allowance > required Fees", async () => {
|
||||
const amount = toBN(feeAmount).add(toBN(fundAmount)).add(toBN(100)).toString(10);
|
||||
await StandardToken.methods.approve(Escrow.options.address, amount).send({from: accounts[0]});
|
||||
await SNT.methods.approve(Escrow.options.address, 1000).send({from: accounts[0]});
|
||||
|
||||
await execute(StandardToken, escrowIdToken);
|
||||
});
|
||||
|
||||
it("Allowance < to required funds. Token is not SNT. SNT Allowance > required Fees", async () => {
|
||||
const amount = toBN(fundAmount).sub(toBN(10)).toString(10);
|
||||
await StandardToken.methods.approve(Escrow.options.address, amount).send({from: accounts[0]});
|
||||
await SNT.methods.approve(Escrow.options.address, 1000).send({from: accounts[0]});
|
||||
|
||||
await execute(StandardToken, escrowIdToken);
|
||||
});
|
||||
|
||||
it("Allowance == to required funds. Token is not SNT. SNT Allowance < required Fees", async () => {
|
||||
await StandardToken.methods.approve(Escrow.options.address, fundAmount).send({from: accounts[0]});
|
||||
await SNT.methods.approve(Escrow.options.address, 1).send({from: accounts[0]});
|
||||
|
||||
await execute(StandardToken, escrowIdToken);
|
||||
});
|
||||
|
||||
it("Allowance > to required funds. Token is not SNT. SNT Allowance < required Fees", async () => {
|
||||
const amount = toBN(feeAmount).add(toBN(fundAmount)).add(toBN(100)).toString(10);
|
||||
await StandardToken.methods.approve(Escrow.options.address, amount).send({from: accounts[0]});
|
||||
await SNT.methods.approve(Escrow.options.address, 1).send({from: accounts[0]});
|
||||
|
||||
await execute(StandardToken, escrowIdToken);
|
||||
});
|
||||
|
||||
it("Allowance < to required funds. Token is not SNT. SNT Allowance < required Fees", async () => {
|
||||
const amount = toBN(fundAmount).sub(toBN(10)).toString(10);
|
||||
await StandardToken.methods.approve(Escrow.options.address, amount).send({from: accounts[0]});
|
||||
await SNT.methods.approve(Escrow.options.address, 1).send({from: accounts[0]});
|
||||
|
||||
await execute(StandardToken, escrowIdToken);
|
||||
});
|
||||
|
||||
const tokenApprovalAndBuildTrx = async (token, escrowId) => {
|
||||
const tokenAllowance = await token.methods.allowance(accounts[0], Escrow.options.address).call();
|
||||
|
||||
const toSend = Escrow.methods.fund(escrowId, fundAmount, expirationTime);
|
||||
const encodedCall = toSend.encodeABI();
|
||||
|
||||
let approvalPromises = [];
|
||||
let trxToSend;
|
||||
|
||||
const resetApproval = (token, tokenAllowance) => {
|
||||
// Reset approval
|
||||
// due to: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
|
||||
if(toBN(tokenAllowance).gt(toBN(0))){
|
||||
approvalPromises.push(token.methods.approve(Escrow.options.address, "0").send({from: accounts[0]}));
|
||||
}
|
||||
};
|
||||
|
||||
if (token.options.address === SNT.options.address){
|
||||
// Both tokens and fee are in SNT.
|
||||
const sntAmount = fundAmount + feeAmount;
|
||||
if(toBN(tokenAllowance).gte(toBN(sntAmount))){
|
||||
trxToSend = toSend;
|
||||
} else {
|
||||
resetApproval(SNT, tokenAllowance);
|
||||
trxToSend = SNT.methods.approveAndCall(Escrow.options.address, sntAmount, encodedCall);
|
||||
}
|
||||
} else {
|
||||
// Verifying token allowance for funding
|
||||
if(toBN(tokenAllowance).lt(toBN(fundAmount))){
|
||||
resetApproval(token, tokenAllowance);
|
||||
approvalPromises.push(token.methods.approve(Escrow.options.address, fundAmount).send({from: accounts[0]}));
|
||||
}
|
||||
|
||||
// Verifying SNT allowance for fees
|
||||
const sntAllowance = await SNT.methods.allowance(accounts[0], Escrow.options.address).call();
|
||||
if(toBN(sntAllowance).gte(toBN(feeAmount))){
|
||||
trxToSend = toSend; // Enough funds. Execute directly.
|
||||
} else {
|
||||
resetApproval(SNT, tokenAllowance); // Has some funds. Reset
|
||||
trxToSend = SNT.methods.approveAndCall(Escrow.options.address, feeAmount, encodedCall);
|
||||
}
|
||||
}
|
||||
|
||||
return { approvalPromises, trxToSend};
|
||||
};
|
||||
});
|
||||
|
||||
});
|
Loading…
Reference in New Issue