snt-gas-relay/test/identity.js

498 lines
18 KiB
JavaScript

const assert = require('assert');
const Embark = require('embark');
let EmbarkSpec = Embark.initTests();
let web3 = EmbarkSpec.web3;
const TestUtils = require("../utils/testUtils.js");
const idUtils = require('../utils/identityUtils.js');
describe("Identity", function() {
this.timeout(0);
let accounts;
beforeEach( function(done) {
this.timeout(0);
EmbarkSpec = Embark.initTests();
web3 = EmbarkSpec.web3;
EmbarkSpec.deployAll({
"Identity": {},
"TestContract": {}
}, (_accounts) => {
accounts = _accounts;
done();
});
});
describe("Identity()", () => {
it("initialize with msg.sender as management key", async () => {
assert.equal(
await Identity.methods.getKeyPurpose(TestUtils.addressToBytes32(accounts[0])).call(),
idUtils.purposes.MANAGEMENT,
Identity.address + ".getKeyPurpose("+accounts[0]+") is not MANAGEMENT_KEY");
});
});
describe("addKey(address _key, uint256 _type)", () => {
it("MANAGEMENT_KEY add a new address as ACTION_KEY", async () => {
await Identity.methods.execute(
Identity.address,
0,
idUtils.encode.addKey(accounts[1], idUtils.purposes.ACTION, idUtils.types.ADDRESS)
).send({from: accounts[0]});
assert.equal(
await Identity.methods.getKeyPurpose(TestUtils.addressToBytes32(accounts[1])).call(),
idUtils.purposes.ACTION,
Identity.address+".getKeyPurpose("+accounts[1]+") is not ACTION_KEY");
});
it("should not add key by non manager", async () => {
try {
await Identity.methods.execute(
Identity.address,
0,
idUtils.encode.addKey(accounts[1], idUtils.purposes.MANAGEMENT, idUtils.types.ADDRESS))
.send({from: accounts[2]});
assert.fail('should have reverted before');
} catch(error) {
TestUtils.assertJump(error);
}
assert.equal(
await Identity.methods.getKeyPurpose(TestUtils.addressToBytes32(accounts[1])).call(),
idUtils.purposes.NONE,
Identity.address+".getKeyPurpose("+accounts[1]+") is not correct");
});
it("should not add key type 1 by actor", async () => {
await Identity.methods.execute(
Identity.address,
0,
idUtils.encode.addKey(accounts[2], idUtils.purposes.ACTION, idUtils.types.ADDRESS))
.send({from: accounts[0]});
try {
await Identity.methods.execute(
Identity.address,
0,
idUtils.encode.addKey(accounts[1], idUtils.purposes.MANAGEMENT, idUtils.types.ADDRESS))
.send({from: accounts[2]});
assert.fail('should have reverted before');
} catch(error) {
TestUtils.assertJump(error);
}
assert.equal(
await Identity.methods.getKeyPurpose(TestUtils.addressToBytes32(accounts[1])).call(),
idUtils.purposes.NONE,
Identity.address+".getKeyType("+accounts[1]+") is not correct");
});
it("fire KeyAdded(address indexed key, uint256 indexed type)", async () => {
let receipt = await Identity.methods.execute(
Identity.address,
0,
idUtils.encode.addKey(accounts[1], idUtils.purposes.MANAGEMENT, idUtils.types.ADDRESS))
.send({from: accounts[0]});
const keyAdded = TestUtils.eventValues(receipt, "KeyAdded");
assert(keyAdded.key, TestUtils.addressToBytes32(accounts[1]), "Key is not correct")
assert(keyAdded.keyType, idUtils.types.ADDRESS, "Type is not correct")
});
});
describe("removeKey(address _key, uint256 _type)", () => {
it("MANAGEMENT_KEY should remove a key", async () => {
await Identity.methods.execute(
Identity.address,
0,
idUtils.encode.addKey(accounts[1], idUtils.purposes.MANAGEMENT, idUtils.types.ADDRESS))
.send({from: accounts[0]});
await Identity.methods.execute(
Identity.address,
0,
idUtils.encode.removeKey(accounts[1], idUtils.purposes.MANAGEMENT))
.send({from: accounts[0]});
assert.equal(
await Identity.methods.getKeyPurpose(TestUtils.addressToBytes32(accounts[1])).call(),
idUtils.purposes.NONE,
Identity.address+".getKeyPurpose("+accounts[1]+") is not 0")
});
it("other key should not remove a key", async () => {
await Identity.methods.execute(
Identity.address,
0,
idUtils.encode.addKey(accounts[1], idUtils.purposes.MANAGEMENT, idUtils.types.ADDRESS))
.send({from: accounts[0]});
try {
await Identity.methods.execute(
Identity.address,
0,
idUtils.encode.removeKey(accounts[1], idUtils.purposes.MANAGEMENT))
.send({from: accounts[2]});
assert.fail('should have reverted before');
} catch(error) {
TestUtils.assertJump(error);
}
assert.equal(
await Identity.methods.getKeyPurpose(TestUtils.addressToBytes32(accounts[1])).call(),
idUtils.purposes.MANAGEMENT,
Identity.address+".getKeyPurpose("+accounts[1]+") is not 0")
});
it("actor key should not remove key", async () => {
await Identity.methods.execute(
Identity.address,
0,
idUtils.encode.addKey(accounts[1], idUtils.purposes.ACTION, idUtils.types.ADDRESS))
.send({from: accounts[0]});
await Identity.methods.execute(
Identity.address,
0,
idUtils.encode.addKey(accounts[2], idUtils.purposes.ACTION, idUtils.types.ADDRESS))
.send({from: accounts[0]});
try {
await Identity.methods.execute(
Identity.address,
0,
idUtils.encode.removeKey(accounts[1], idUtils.purposes.ACTION))
.send({from: accounts[2]});
assert.fail('should have reverted before');
} catch(error) {
TestUtils.assertJump(error);
}
assert.equal(
await Identity.methods.getKeyPurpose(TestUtils.addressToBytes32(accounts[1])).call(),
idUtils.purposes.ACTION,
Identity.address+".getKeyType("+accounts[1]+") is not 0")
});
it("MANAGEMENT_KEY should not remove itself MANAGEMENT_KEY when there is no other MANAGEMENT_KEY", async () => {
await Identity.methods.execute(
Identity.address,
0,
idUtils.encode.removeKey(accounts[0], idUtils.purposes.MANAGEMENT))
.send({from: accounts[0]});
assert.equal(
await Identity.methods.getKeyPurpose(TestUtils.addressToBytes32(accounts[0])).call(),
idUtils.purposes.MANAGEMENT,
Identity.address+".getKeyType("+accounts[0]+") is not 1")
});
it("fire KeyRemoved(address indexed key, uint256 indexed type)", async () => {
await Identity.methods.execute(
Identity.address,
0,
idUtils.encode.addKey(accounts[1], idUtils.purposes.ACTION, idUtils.types.ADDRESS))
.send({from: accounts[0]});
let receipt = await Identity.methods.execute(
Identity.address,
0,
idUtils.encode.removeKey(accounts[1], idUtils.purposes.ACTION))
.send({from: accounts[0]});
const keyRemoved = TestUtils.eventValues(receipt, "KeyRemoved");
assert(keyRemoved.key, TestUtils.addressToBytes32(accounts[1]), "Key is not correct");
assert(keyRemoved.keyType, idUtils.types.ADDRESS, "Type is not correct");
});
});
describe("getKeyPurpose(address _key)", () => {
it("should start only with initializer as only key", async () => {
assert.equal(
await Identity.methods.getKeyPurpose(TestUtils.addressToBytes32(accounts[0])).call(),
idUtils.purposes.MANAGEMENT,
Identity.address+".getKeyPurpose("+accounts[0]+") is not correct")
assert.equal(
await Identity.methods.getKeyPurpose(TestUtils.addressToBytes32(accounts[1])).call(),
idUtils.purposes.NONE,
Identity.address+".getKeyPurpose("+accounts[1]+") is not correct")
});
it("should get type 2 after addKey type 2", async () => {
await Identity.methods.execute(
Identity.address,
0,
idUtils.encode.addKey(accounts[1], idUtils.purposes.ACTION, idUtils.types.ADDRESS))
.send({from: accounts[0]});
assert.equal(
await Identity.methods.getKeyPurpose(TestUtils.addressToBytes32(accounts[1])).call(),
idUtils.purposes.ACTION,
Identity.address+".getKeyPurpose("+accounts[1]+") is not correct")
});
it("should get type 3 after addKey type 3", async () => {
await Identity.methods.execute(
Identity.address,
0,
idUtils.encode.addKey(accounts[1], idUtils.purposes.CLAIM_SIGNER, idUtils.types.ADDRESS))
.send({from: accounts[0]});
assert.equal(
await Identity.methods.getKeyPurpose(TestUtils.addressToBytes32(accounts[1])).call(),
idUtils.purposes.CLAIM_SIGNER,
Identity.address+".getKeyPurpose("+accounts[1]+") is not correct")
});
});
/*
describe("getKeysByType(uint256 _type)", () => {
it("at initialization", async () => {
});
it("after addKey", async () => {
});
it("after removeKey", async () => {
});
});
*/
describe("execute(address _to, uint256 _value, bytes _data)", () => {
let functionPayload;
it("Identity should receive ether", async() => {
const amountToSend = web3.utils.toWei('0.05', "ether");
let idBalance0 = await web3.eth.getBalance(Identity.address);
await web3.eth.sendTransaction({from:accounts[0], to:Identity.address, value: amountToSend})
let idBalance1 = await web3.eth.getBalance(Identity.address);
assert.equal(web3.utils.toBN(idBalance0).add(web3.utils.toBN(amountToSend)).toString(), web3.utils.toBN(idBalance1).toString(), Identity.address + " did not receive ether");
});
it("ACTOR_KEY execute arbitrary transaction", async () => {
await Identity.methods.execute(
Identity.address,
0,
idUtils.encode.addKey(accounts[1], idUtils.purposes.ACTION, idUtils.types.ADDRESS))
.send({from: accounts[0]});
functionPayload = web3.eth.abi.encodeFunctionCall({
name: 'test',
type: 'function',
inputs: []
}, []);
let receipt = await Identity.methods.execute(
TestContract.address,
0,
functionPayload)
.send({from: accounts[1]});
// @rramos - Commented because of error:
// The current provider doesn't support subscriptions: Provider
/*assert.notEqual(
await TestUtils.listenForEvent(TestContract.events.TestFunctionExecuted),
undefined,
"Test function was not executed"); */
});
it("MANAGEMENT_KEY cannot execute arbitrary transaction", async () => {
try {
await Identity.methods.execute(
TestContract.address,
0,
functionPayload)
.send({from: accounts[0]});
} catch(error) {
TestUtils.assertJump(error);
}
});
it("Other keys NOT execute arbitrary transaction", async () => {
try {
await Identity.methods.execute(
TestContract.address,
0,
functionPayload)
.send({from: accounts[3]});
assert.fail('should have reverted before');
} catch(error) {
TestUtils.assertJump(error);
}
});
it("ACTION_KEY should send ether from contract", async () => {
await Identity.methods.execute(
Identity.address,
0,
idUtils.encode.addKey(accounts[1], idUtils.purposes.ACTION, idUtils.types.ADDRESS))
.send({from: accounts[0]});
// Adding funds to contract
await web3.eth.sendTransaction({from:accounts[0], to:Identity.address, value: web3.utils.toWei('0.05', "ether")})
const amountToSend = web3.utils.toWei('0.01', "ether");
let idBalance0 = await web3.eth.getBalance(Identity.address);
let a2Balance0 = await web3.eth.getBalance(accounts[2]);
await Identity.methods.execute(
accounts[2],
amountToSend,
'0x')
.send({from: accounts[1]});
let idBalance1 = await web3.eth.getBalance(Identity.address);
let a2Balance1 = await web3.eth.getBalance(accounts[2]);
assert(web3.utils.toBN(idBalance1).toString(), web3.utils.toBN(idBalance0).sub(web3.utils.toBN(amountToSend)).toString(), "Contract did not send ether");
assert(web3.utils.toBN(a2Balance1).toString(), web3.utils.toBN(a2Balance0).add(web3.utils.toBN(amountToSend)).toString(), accounts[2] + " did not receive ether");
});
it("fire ExecutionRequested(uint256 indexed executionId, address indexed to, uint256 indexed value, bytes data)", async () => {
await Identity.methods.execute(
Identity.address,
0,
idUtils.encode.addKey(accounts[1], idUtils.purposes.ACTION, idUtils.types.ADDRESS))
.send({from: accounts[0]});
let receipt = await Identity.methods.execute(
TestContract.address,
0,
functionPayload)
.send({from: accounts[1]});
const executionRequested = TestUtils.eventValues(receipt, "ExecutionRequested");
assert(executionRequested.to, TestContract.address, "To is not correct");
assert(executionRequested.value, 0, "Value is not correct");
assert(executionRequested.data, functionPayload, "Data is not correct");
});
it("fire Executed(uint256 indexed executionId, address indexed to, uint256 indexed value, bytes data)", async () => {
await Identity.methods.execute(
Identity.address,
0,
idUtils.encode.addKey(accounts[1], idUtils.purposes.ACTION, idUtils.types.ADDRESS))
.send({from: accounts[0]});
let receipt = await Identity.methods.execute(
TestContract.address,
0,
functionPayload)
.send({from: accounts[1]});
const executed = TestUtils.eventValues(receipt, "Executed")
assert(executed.to, TestContract.address, "To is not correct");
assert(executed.value, 0, "Value is not correct");
assert(executed.data, functionPayload, "Data is not correct");
});
});
/*
describe("setMinimumApprovalsByKeyPurpose(uint256 _type, uint8 _minimumApprovals)", () => {
it("MANAGEMENT_KEY should set minimum approvals for MANAGEMENT_KEYs", async () => {
});
it("MANAGEMENT_KEY should set minimum approvals for ACTION_KEYs", async () => {
});
it("ACTION_KEY should not be able to set minimum approvals", async () => {
});
it("Other keys should not be able to set minimum approvals", async () => {
});
});
describe("approve(bytes32 _id, bool _approve)", () => {
it("MANAGEMENT_KEY should approve a claim", async () => {
});
it("MANAGEMENT_KEY should approve a transaction", async () => {
});
it("2 out of 3 MANAGEMENT_KEY should approve a transaction and execute it", async () => {
});
it("fire Approved(uint256 indexed executionId, bool approved)", async () => {
});
});
describe("getClaim(bytes32 _claimId)", () => {
it("Returns a claim by ID.", async () => {
});
});
describe("getClaimIdsByType(uint256 _claimType)", () => {
it("Returns an array of claim IDs by type.", async () => {
});
});
describe("addClaim(uint256 _claimType, address issuer, uint256 signatureType, bytes _signature, bytes _data, string _uri)", () => {
it("Requests the ADDITION of a claim from an issuer", async () => {
});
it("Requests the CHANGE of a claim from an issuer", async () => {
});
});
describe("removeClaim(bytes32 _claimId)", () => {
it("Requests the DELETION of a claim from an issuer", async () => {
});
it("Requests the DELETION of a claim from identity", async () => {
});
});
*/
});