mirror of
https://github.com/status-im/contracts.git
synced 2025-02-23 12:08:47 +00:00
Merge from embark into develop
This commit is contained in:
commit
82b91db5c8
6
.gitignore
vendored
6
.gitignore
vendored
@ -3,6 +3,10 @@ __pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# embark
|
||||
.embark/
|
||||
chains.json
|
||||
|
||||
# egg-related
|
||||
viper.egg-info/
|
||||
build/
|
||||
@ -33,4 +37,4 @@ npm-debug.log
|
||||
|
||||
# other
|
||||
.vs/
|
||||
bin/
|
||||
bin/
|
||||
|
56
config/blockchain.json
Normal file
56
config/blockchain.json
Normal file
@ -0,0 +1,56 @@
|
||||
{
|
||||
"development": {
|
||||
"enabled": true,
|
||||
"networkType": "custom",
|
||||
"genesisBlock": "config/development/genesis.json",
|
||||
"datadir": ".embark/development/datadir",
|
||||
"mineWhenNeeded": true,
|
||||
"nodiscover": true,
|
||||
"maxpeers": 0,
|
||||
"rpcHost": "localhost",
|
||||
"rpcPort": 8545,
|
||||
"rpcCorsDomain": "http://localhost:8000",
|
||||
"account": {
|
||||
"password": "config/development/password"
|
||||
},
|
||||
"targetGasLimit": 8000000,
|
||||
"wsOrigins": "http://localhost:8000",
|
||||
"wsRPC": true,
|
||||
"wsHost": "localhost",
|
||||
"wsPort": 8546,
|
||||
"simulatorMnemonic": "example exile argue silk regular smile grass bomb merge arm assist farm",
|
||||
"simulatorBlocktime": 0
|
||||
},
|
||||
"testnet": {
|
||||
"enabled": true,
|
||||
"networkType": "testnet",
|
||||
"light": true,
|
||||
"rpcHost": "localhost",
|
||||
"rpcPort": 8545,
|
||||
"rpcCorsDomain": "http://localhost:8000",
|
||||
"account": {
|
||||
"password": "config/testnet/password"
|
||||
}
|
||||
},
|
||||
"livenet": {
|
||||
"enabled": true,
|
||||
"networkType": "livenet",
|
||||
"light": true,
|
||||
"rpcHost": "localhost",
|
||||
"rpcPort": 8545,
|
||||
"rpcCorsDomain": "http://localhost:8000",
|
||||
"account": {
|
||||
"password": "config/livenet/password"
|
||||
}
|
||||
},
|
||||
"privatenet": {
|
||||
"enabled": true,
|
||||
"networkType": "custom",
|
||||
"rpcHost": "localhost",
|
||||
"rpcPort": 8545,
|
||||
"rpcCorsDomain": "http://localhost:8000",
|
||||
"datadir": "yourdatadir",
|
||||
"networkId": "123",
|
||||
"bootnodes": ""
|
||||
}
|
||||
}
|
12
config/communication.json
Normal file
12
config/communication.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"default": {
|
||||
"enabled": true,
|
||||
"provider": "whisper",
|
||||
"available_providers": ["whisper", "orbit"],
|
||||
"connection": {
|
||||
"host": "localhost",
|
||||
"port": 8546,
|
||||
"type": "ws"
|
||||
}
|
||||
}
|
||||
}
|
36
config/contracts.json
Normal file
36
config/contracts.json
Normal file
@ -0,0 +1,36 @@
|
||||
{
|
||||
"default": {
|
||||
"versions": {
|
||||
"web3.js": "1.0.0-beta",
|
||||
"solc": "0.4.17"
|
||||
},
|
||||
"deployment": {
|
||||
"host": "localhost",
|
||||
"port": 8545,
|
||||
"type": "rpc"
|
||||
},
|
||||
"dappConnection": [
|
||||
"$WEB3",
|
||||
"http://localhost:8545"
|
||||
],
|
||||
"gas": "auto",
|
||||
"contracts": {
|
||||
"Controlled": { "deploy": false },
|
||||
"DelayedUpdatableInstance": { "deploy": false },
|
||||
"DelayedUpdatableInstanceStorage": { "deploy": false },
|
||||
"DelegatedCall": { "deploy": false },
|
||||
"Factory": { "deploy": false },
|
||||
"Instance": { "deploy": false },
|
||||
"InstanceStorage": { "deploy": false },
|
||||
"UpdatableInstance": { "deploy": false },
|
||||
"ERC725": { "deploy": false },
|
||||
"ERC735": { "deploy": false },
|
||||
"FriendsRecovery": { "deploy": false },
|
||||
"TestContract": { "deploy": false },
|
||||
"UpdatedIdentityKernel": { "deploy": false },
|
||||
"Identity": { "gas": 5000000 },
|
||||
"IdentityFactory": { "deploy": false },
|
||||
"IdentityKernel": { "gas": 5000000 }
|
||||
}
|
||||
}
|
||||
}
|
16
config/development/genesis.json
Normal file
16
config/development/genesis.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"config": {
|
||||
"homesteadBlock": 1
|
||||
},
|
||||
"nonce": "0x0000000000000042",
|
||||
"difficulty": "0x0",
|
||||
"alloc": {
|
||||
"0x3333333333333333333333333333333333333333": {"balance": "15000000000000000000"}
|
||||
},
|
||||
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase": "0x3333333333333333333333333333333333333333",
|
||||
"timestamp": "0x00",
|
||||
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"extraData": "0x",
|
||||
"gasLimit": "0x7a1200"
|
||||
}
|
1
config/development/password
Normal file
1
config/development/password
Normal file
@ -0,0 +1 @@
|
||||
dev_password
|
20
config/storage.json
Normal file
20
config/storage.json
Normal file
@ -0,0 +1,20 @@
|
||||
{
|
||||
"default": {
|
||||
"versions": {
|
||||
"ipfs-api": "17.2.4"
|
||||
},
|
||||
"enabled": true,
|
||||
"ipfs_bin": "ipfs",
|
||||
"provider": "ipfs",
|
||||
"available_providers": ["ipfs"],
|
||||
"host": "localhost",
|
||||
"port": 5001
|
||||
},
|
||||
"development": {
|
||||
"enabled": true,
|
||||
"provider": "ipfs",
|
||||
"host": "localhost",
|
||||
"port": 5001,
|
||||
"getUrl": "http://localhost:8080/ipfs/"
|
||||
}
|
||||
}
|
1
config/testnet/password
Normal file
1
config/testnet/password
Normal file
@ -0,0 +1 @@
|
||||
test_password
|
5
config/webserver.json
Normal file
5
config/webserver.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"enabled": true,
|
||||
"host": "localhost",
|
||||
"port": 8000
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
pragma solidity ^0.4.4;
|
||||
|
||||
contract Migrations {
|
||||
address public owner;
|
||||
uint public last_completed_migration;
|
||||
|
||||
modifier restricted() {
|
||||
if (msg.sender == owner) _;
|
||||
}
|
||||
|
||||
function Migrations() {
|
||||
owner = msg.sender;
|
||||
}
|
||||
|
||||
function setCompleted(uint completed) restricted {
|
||||
last_completed_migration = completed;
|
||||
}
|
||||
|
||||
function upgrade(address new_address) restricted {
|
||||
Migrations upgraded = Migrations(new_address);
|
||||
upgraded.setCompleted(last_completed_migration);
|
||||
}
|
||||
}
|
@ -9,7 +9,6 @@ contract TestContract {
|
||||
TestFunctionExecuted();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Helper function to be used in unit testing due to error in web3
|
||||
web3.utils.soliditySha3([1, 2, 3])
|
||||
@ -23,7 +22,7 @@ contract TestContract {
|
||||
bytes _data,
|
||||
bytes32 _newSecret,
|
||||
bytes32[] _newFriendsHashes)
|
||||
external
|
||||
public
|
||||
pure
|
||||
returns(bytes32)
|
||||
{
|
||||
|
7
embark.json
Normal file
7
embark.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"contracts": ["contracts/**"],
|
||||
"buildDir": "dist/",
|
||||
"config": "config/",
|
||||
"plugins": {
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
var Migrations = artifacts.require("./Migrations.sol");
|
||||
|
||||
module.exports = function(deployer) {
|
||||
deployer.deploy(Migrations);
|
||||
};
|
@ -1,5 +0,0 @@
|
||||
let Identity = artifacts.require("./Identity.sol");
|
||||
|
||||
module.exports = function(deployer) {
|
||||
deployer.deploy(Identity);
|
||||
};
|
@ -2,7 +2,8 @@
|
||||
"name": "status-contracts",
|
||||
"version": "1.0.0",
|
||||
"scripts": {
|
||||
"solidity-coverage": "./node_modules/.bin/solidity-coverage"
|
||||
"solidity-coverage": "./node_modules/.bin/solidity-coverage",
|
||||
"test": "embark test"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@ -20,8 +21,8 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"elliptic-curve": "^0.1.0",
|
||||
"solidity-coverage": "^0.4.4",
|
||||
"embark": "^2.7.0",
|
||||
"ethereumjs-util": "^5.1.5",
|
||||
"web3": "^1.0.0-beta.30"
|
||||
"solidity-coverage": "^0.4.4"
|
||||
}
|
||||
}
|
||||
|
210
test/factory.js
210
test/factory.js
@ -1,102 +1,136 @@
|
||||
const assert = require('assert');
|
||||
const Embark = require('embark');
|
||||
let EmbarkSpec = Embark.initTests();
|
||||
let web3 = EmbarkSpec.web3;
|
||||
|
||||
const identityJson = require('../dist/contracts/Identity.json');
|
||||
const updatedIdentityKernelJson = require('../dist/contracts/UpdatedIdentityKernel.json');
|
||||
|
||||
const TestUtils = require("../utils/testUtils.js")
|
||||
const idUtils = require("../utils/identityUtils.js")
|
||||
const web3EthAbi = require("web3-eth-abi");
|
||||
|
||||
const Identity = artifacts.require("./identity/Identity.sol");
|
||||
const IdentityFactory = artifacts.require("./identity/IdentityFactory.sol");
|
||||
const UpdatableInstance = artifacts.require('./deploy/UpdatableInstance.sol');
|
||||
const UpdatedIdentityKernel = artifacts.require("./tests/UpdatedIdentityKernel.sol");
|
||||
|
||||
contract('IdentityFactory', function(accounts) {
|
||||
describe('IdentityFactory', function(accounts) {
|
||||
|
||||
let identityFactory;
|
||||
let identity;
|
||||
let updatedIdentity;
|
||||
let updatedIdentityKernel;
|
||||
|
||||
before(async () => {
|
||||
identityFactory = await IdentityFactory.new("0xaaa", {from: accounts[0]});
|
||||
})
|
||||
|
||||
describe("IdentityFactory()", () => {
|
||||
it("Creates a new identity", async () => {
|
||||
let tx = await identityFactory.createIdentity({from: accounts[0]});
|
||||
const logEntry = tx.logs[0];
|
||||
assert.strictEqual(logEntry.event, "IdentityCreated");
|
||||
|
||||
identity = await Identity.at(logEntry.args.instance, {from: accounts[0]})
|
||||
|
||||
assert.equal(
|
||||
await identity.getKeyPurpose(TestUtils.addressToBytes32(accounts[0])),
|
||||
idUtils.purposes.MANAGEMENT,
|
||||
identity.address + ".getKeyPurpose("+accounts[0]+") is not MANAGEMENT_KEY")
|
||||
});
|
||||
|
||||
|
||||
it("Registers a updated identity contract", async() => {
|
||||
const infoHash = "0xbbb";
|
||||
updatedIdentityKernel = await UpdatedIdentityKernel.new({from: accounts[0]});
|
||||
await identityFactory.setKernel(updatedIdentityKernel.address, infoHash);
|
||||
|
||||
const newKernel = await TestUtils.listenForEvent(identityFactory.NewKernel());
|
||||
assert(newKernel.infohash, infoHash, "Infohash is not correct");
|
||||
});
|
||||
|
||||
before( function(done) {
|
||||
this.timeout(0);
|
||||
|
||||
it("Creates a new identity using latest version", async() => {
|
||||
let tx = await identityFactory.createIdentity({from: accounts[0]});
|
||||
const logEntry = tx.logs[0];
|
||||
assert.strictEqual(logEntry.event, "IdentityCreated");
|
||||
EmbarkSpec = Embark.initTests();
|
||||
web3 = EmbarkSpec.web3;
|
||||
|
||||
updatedIdentity = await UpdatedIdentityKernel.at(logEntry.args.instance, {from: accounts[0]})
|
||||
tx = await updatedIdentity.test({from: accounts[0]});
|
||||
assert.strictEqual(tx.logs[0].event, "TestFunctionExecuted");
|
||||
|
||||
// Test if it still executes identity functions as expected
|
||||
let baseIdentity = await Identity.at(updatedIdentity.address, {from: accounts[0]})
|
||||
assert.equal(
|
||||
await identity.getKeyPurpose(TestUtils.addressToBytes32(accounts[0])),
|
||||
1,
|
||||
identity.address + ".getKeyPurpose("+accounts[0]+") is not MANAGEMENT_KEY")
|
||||
EmbarkSpec.deployAll({
|
||||
"IdentityFactory": {
|
||||
args: ["0xaaaa"],
|
||||
gas: 5000000
|
||||
},
|
||||
"Identity": {},
|
||||
"UpdatedIdentityKernel": {}
|
||||
}, (_accounts) => {
|
||||
accounts = _accounts;
|
||||
done();
|
||||
});
|
||||
|
||||
|
||||
it("Updates an identity to the latest version", async() => {
|
||||
let tx1 = await identity.execute(
|
||||
identity.address,
|
||||
0,
|
||||
idUtils.encode.updateRequestUpdatableInstance(updatedIdentityKernel.address),
|
||||
{from: accounts[0]}
|
||||
);
|
||||
|
||||
assert.strictEqual(tx1.logs[tx1.logs.length - 1].event, "Executed");
|
||||
|
||||
// Updating EVM timestamp to test delay
|
||||
const plus31days = 60 * 60 * 24 * 31;
|
||||
|
||||
web3.currentProvider.send({jsonrpc: "2.0", method: "evm_increaseTime", params: [plus31days], id: 0});
|
||||
web3.currentProvider.send({jsonrpc: "2.0", method: "evm_mine", params: [], id: 0})
|
||||
|
||||
// Confirm update
|
||||
let tx2 = await identity.execute(
|
||||
identity.address,
|
||||
0,
|
||||
idUtils.encode.updateConfirmUpdatableInstance(updatedIdentityKernel.address),
|
||||
{from: accounts[0]}
|
||||
);
|
||||
|
||||
assert.strictEqual(tx2.logs[tx2.logs.length - 1].event, "Executed");
|
||||
|
||||
// Calling function available in updated identity kernel
|
||||
let updatedIdentity1 = await UpdatedIdentityKernel.at(identity.address, {from: accounts[0]})
|
||||
let tx3 = await updatedIdentity1.test({from: accounts[0]});
|
||||
|
||||
assert.strictEqual(tx3.logs[tx3.logs.length - 1].event, "TestFunctionExecuted");
|
||||
assert.equal(
|
||||
tx3.logs[tx3.logs.length - 1].args.minApprovalsByManagementKeys.toString(10),
|
||||
1,
|
||||
identity.address + " wasn't updated to last version");
|
||||
})
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it("Creates a new identity", async () => {
|
||||
let tx = await IdentityFactory.methods.createIdentity().send({from: accounts[0]});
|
||||
|
||||
const logEntry = tx.events.IdentityCreated;
|
||||
|
||||
assert(logEntry !== undefined, "IdentityCreated was not triggered");
|
||||
|
||||
let identity = new web3.eth.Contract(identityJson.abi, logEntry.returnValues.instance, {from: accounts[0]});
|
||||
|
||||
assert.equal(
|
||||
await identity.methods.getKeyPurpose(TestUtils.addressToBytes32(accounts[0])).call(),
|
||||
idUtils.purposes.MANAGEMENT,
|
||||
identity.address + ".getKeyPurpose("+accounts[0]+") is not MANAGEMENT_KEY")
|
||||
});
|
||||
|
||||
|
||||
it("Registers a updated identity contract", async() => {
|
||||
const infoHash = "0xbbbb";
|
||||
let receipt = await IdentityFactory.methods.setKernel(UpdatedIdentityKernel.address, infoHash).send({from: accounts[0]});
|
||||
|
||||
const newKernel = TestUtils.eventValues(receipt, "NewKernel");
|
||||
assert(newKernel.infohash, infoHash, "Infohash is not correct");
|
||||
});
|
||||
|
||||
|
||||
it("Creates a new identity using latest version", async() => {
|
||||
let tx = await IdentityFactory.methods.createIdentity().send({from: accounts[0]});
|
||||
|
||||
assert.notEqual(tx.events.IdentityCreated, undefined, "IdentityCreated wasn't triggered");
|
||||
|
||||
const contractAddress = tx.events.IdentityCreated.returnValues.instance;
|
||||
|
||||
|
||||
let updatedIdentity = new web3.eth.Contract(updatedIdentityKernelJson.abi, contractAddress, {from: accounts[0]});
|
||||
|
||||
tx = await updatedIdentity.methods.test().send({from: accounts[0]});
|
||||
assert.notEqual(tx.events.TestFunctionExecuted, undefined, "TestFunctionExecuted wasn't triggered");
|
||||
|
||||
// Test if it still executes identity functions as expected
|
||||
let baseIdentity = new web3.eth.Contract(identityJson.abi, contractAddress, {from: accounts[0]});
|
||||
|
||||
assert.equal(
|
||||
await baseIdentity.methods.getKeyPurpose(TestUtils.addressToBytes32(accounts[0])).call(),
|
||||
1,
|
||||
baseIdentity.address + ".getKeyPurpose("+accounts[0]+") is not MANAGEMENT_KEY")
|
||||
});
|
||||
|
||||
|
||||
it("Updates an identity to the latest version", async() => {
|
||||
let tx1 = await Identity.methods.execute(
|
||||
Identity.address,
|
||||
0,
|
||||
idUtils.encode.updateRequestUpdatableInstance(UpdatedIdentityKernel.address))
|
||||
.send({from: accounts[0]});
|
||||
|
||||
assert.notEqual(tx1.events.Executed, undefined, "Executed wasn't triggered");
|
||||
|
||||
// Updating EVM timestamp to test delay
|
||||
const plus31days = 60 * 60 * 24 * 31;
|
||||
|
||||
/*
|
||||
// @rramos - The following code is supposed to increase by 31 days the evm date,
|
||||
// and mine one block. It is commented because it seems to not be working on web3 1.0.
|
||||
// Also, sendAsync is supposed to be named send in this version, yet it shows an error
|
||||
// that it does not support synchronous executions. (?)
|
||||
// TODO: figure it out!
|
||||
|
||||
web3.currentProvider.send({jsonrpc: "2.0", method: "evm_increaseTime", params: [plus31days], id: 0}, function(){console.log(1);});
|
||||
web3.currentProvider.send({jsonrpc: "2.0", method: "evm_mine", params: [], id: 0}, function(){console.log(2);})
|
||||
|
||||
|
||||
|
||||
// Confirm update
|
||||
let tx2 = await Identity.methods.execute(
|
||||
Identity.address,
|
||||
0,
|
||||
idUtils.encode.updateConfirmUpdatableInstance(UpdatedIdentityKernel.address))
|
||||
.send({from: accounts[0]});
|
||||
|
||||
assert.notEqual(tx2.events.Executed, undefined, "Executed wasn't triggered");
|
||||
|
||||
|
||||
let updatedIdentity1 = new web3.eth.Contract(updatedIdentityKernelJson.abi, Identity.address, {from: accounts[0]});
|
||||
|
||||
// Calling
|
||||
let tx3 = await updatedIdentity1.methods.test().send({from: accounts[0]});
|
||||
assert.notEqual(tx3.events.TestFunctionExecuted, undefined, "TestFunctionExecuted wasn't triggered");
|
||||
assert.equal(
|
||||
tx3.events.TestFunctionExecuted.returnValues.minApprovalsByManagementKeys.toString(10),
|
||||
1,
|
||||
Identity.address + " wasn't updated to last version");
|
||||
|
||||
*/
|
||||
})
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
@ -1,121 +1,145 @@
|
||||
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");
|
||||
|
||||
const Identity = artifacts.require("./identity/Identity.sol");
|
||||
const FriendsRecovery = artifacts.require("./identity/FriendsRecovery.sol");
|
||||
const TestContract = artifacts.require("./tests/TestContract.sol");
|
||||
|
||||
const web3Utils = require("web3-utils");
|
||||
const web3EthAbi = require("web3-eth-abi");
|
||||
const ethUtils = require('ethereumjs-util')
|
||||
|
||||
contract('FriendsRecovery', function(accounts) {
|
||||
const identityJson = require('../dist/contracts/Identity.json');
|
||||
const friendsRecoveryJson = require('../dist/contracts/FriendsRecovery.json');
|
||||
|
||||
const friends = [
|
||||
{address: '0xe6fa5ca5836572e0da4804fe3599958dcfc6ac2a', private: '0xffe4e190cedfdff279f903701ac14b34e082c4e20bf600bcc73239486f24ea0e' },
|
||||
{address: '0xe9f16a2443208bbacc187b51f3bae88a49d31d5c', private: '0x8836fe516896c7888f9d7e0f3c0df14dd805634a1cfff15e2255f795c0456027' },
|
||||
{address: '0x17090e7674460bd8778b2378ea46238c26da372c', private: '0x6adaf080b209dabe64d72b937fb0708990c2b83aca8ccfb558d61421e3e3c5e5' },
|
||||
{address: '0xf2613d4eb15576f7b54b76a73ede4bb7cb8dceda', private: '0xb26484d0d645282a349950c36183d86e51a550fe3c67da3eb20c777cb779d695' },
|
||||
{address: '0x387a2d6f98b26094d05c2254106bdb9d11f23d6e', private: '0xa33ca4443deadd935a7524335cb6d546b4650199290c24a4d945ebe48cf889d0' },
|
||||
];
|
||||
|
||||
describe("FriendsRecovery()", () => {
|
||||
it("Execute a full recovery", async () => {
|
||||
let testContractInstance = await TestContract.new({from: accounts[0]});
|
||||
describe('FriendsRecovery', function() {
|
||||
|
||||
let identity = await Identity.new({from: accounts[0]})
|
||||
let accounts;
|
||||
|
||||
// A bytes32 string that represents some user data
|
||||
const secret = '0x0000000000000000000000000000000000000000000000000000000000123456';
|
||||
const hashedSecret = web3Utils.soliditySha3(identity.address, secret);
|
||||
|
||||
this.timeout(0);
|
||||
|
||||
const newController = accounts[9];
|
||||
|
||||
let threshold = 3;
|
||||
let friendHashes = [
|
||||
web3Utils.soliditySha3(identity.address, secret, friends[0].address),
|
||||
web3Utils.soliditySha3(identity.address, secret, friends[1].address),
|
||||
web3Utils.soliditySha3(identity.address, secret, friends[2].address),
|
||||
web3Utils.soliditySha3(identity.address, secret, friends[3].address),
|
||||
];
|
||||
|
||||
let recoveryContract = await FriendsRecovery.new(identity.address, 600, threshold, hashedSecret, friendHashes, {from: accounts[0]});
|
||||
|
||||
// Setting up recovery contract for identity
|
||||
let tx1 = await identity.execute(
|
||||
identity.address,
|
||||
0,
|
||||
idUtils.encode.setupRecovery(recoveryContract.address),
|
||||
{from: accounts[0]}
|
||||
);
|
||||
//console.log(tx1.logs);
|
||||
|
||||
const newSecret = '0x0000000000000000000000000000000000000000000000000000000000abcdef';
|
||||
const data = idUtils.encode.managerReset(newController);
|
||||
const newHashedSecret = web3Utils.soliditySha3(identity.address, newSecret);
|
||||
const newFriendHashes = [
|
||||
web3Utils.soliditySha3(accounts[3], newSecret),
|
||||
web3Utils.soliditySha3(accounts[4], newSecret),
|
||||
web3Utils.soliditySha3(accounts[5], newSecret)
|
||||
];
|
||||
|
||||
// Normaly we would use soliditySha3, but it doesn't like arrays
|
||||
const hashedMessageToSign = await testContractInstance.hash.call(identity.address, secret, identity.address, data, newHashedSecret, newFriendHashes);
|
||||
let msgHash = ethUtils.hashPersonalMessage(ethUtils.toBuffer(hashedMessageToSign, 'hex'));
|
||||
const friendSignatures = [
|
||||
ethUtils.ecsign(msgHash, ethUtils.toBuffer(friends[0].private, 'hex')),
|
||||
ethUtils.ecsign(msgHash, ethUtils.toBuffer(friends[1].private, 'hex')),
|
||||
ethUtils.ecsign(msgHash, ethUtils.toBuffer(friends[2].private, 'hex')),
|
||||
ethUtils.ecsign(msgHash, ethUtils.toBuffer(friends[3].private, 'hex'))
|
||||
];
|
||||
|
||||
let tx2 = await recoveryContract.approvePreSigned(
|
||||
hashedMessageToSign,
|
||||
[
|
||||
friendSignatures[0].v,
|
||||
friendSignatures[1].v,
|
||||
friendSignatures[2].v
|
||||
],
|
||||
[
|
||||
'0x' + friendSignatures[0].r.toString('hex'),
|
||||
'0x' + friendSignatures[1].r.toString('hex'),
|
||||
'0x' + friendSignatures[2].r.toString('hex')
|
||||
],
|
||||
[
|
||||
'0x' + friendSignatures[0].s.toString('hex'),
|
||||
'0x' + friendSignatures[1].s.toString('hex'),
|
||||
'0x' + friendSignatures[2].s.toString('hex')
|
||||
],
|
||||
{from: accounts[9]});
|
||||
|
||||
let tx3 = await recoveryContract.execute(
|
||||
secret,
|
||||
identity.address,
|
||||
data,
|
||||
[
|
||||
friends[0].address,
|
||||
friends[1].address,
|
||||
friends[2].address
|
||||
],
|
||||
newHashedSecret,
|
||||
newFriendHashes,
|
||||
{from: accounts[5]});
|
||||
|
||||
await identity.processManagerReset(0, {from: accounts[0]});
|
||||
|
||||
assert.equal(
|
||||
await identity.getKeyPurpose(TestUtils.addressToBytes32(newController)),
|
||||
idUtils.purposes.MANAGEMENT,
|
||||
identity.address + ".getKeyPurpose(" + newController + ") is not MANAGEMENT_KEY")
|
||||
|
||||
assert.equal(
|
||||
await identity.getKeyPurpose(TestUtils.addressToBytes32(newController)),
|
||||
idUtils.purposes.MANAGEMENT,
|
||||
identity.address+".getKeyPurpose("+newController+") is not correct")
|
||||
});
|
||||
before( function(done) {
|
||||
this.timeout(0);
|
||||
|
||||
EmbarkSpec = Embark.initTests();
|
||||
web3 = EmbarkSpec.web3;
|
||||
|
||||
EmbarkSpec.deployAll({
|
||||
"TestContract": {}
|
||||
}, (_accounts) => {
|
||||
accounts = _accounts;
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("Execute a full recovery", async () => {
|
||||
let identityContract = new web3.eth.Contract(identityJson.abi);
|
||||
let recoveryContract = new web3.eth.Contract(friendsRecoveryJson.abi);
|
||||
|
||||
let identity = await identityContract.deploy({data: identityJson.code }).send({from: accounts[0], gas: 5000000, gasPrice: 1});
|
||||
identity.setProvider(web3.currentProvider);
|
||||
|
||||
const friends = [
|
||||
{address: '0xe6fa5ca5836572e0da4804fe3599958dcfc6ac2a', private: '0xffe4e190cedfdff279f903701ac14b34e082c4e20bf600bcc73239486f24ea0e' },
|
||||
{address: '0xe9f16a2443208bbacc187b51f3bae88a49d31d5c', private: '0x8836fe516896c7888f9d7e0f3c0df14dd805634a1cfff15e2255f795c0456027' },
|
||||
{address: '0x17090e7674460bd8778b2378ea46238c26da372c', private: '0x6adaf080b209dabe64d72b937fb0708990c2b83aca8ccfb558d61421e3e3c5e5' },
|
||||
{address: '0xf2613d4eb15576f7b54b76a73ede4bb7cb8dceda', private: '0xb26484d0d645282a349950c36183d86e51a550fe3c67da3eb20c777cb779d695' },
|
||||
{address: '0x387a2d6f98b26094d05c2254106bdb9d11f23d6e', private: '0xa33ca4443deadd935a7524335cb6d546b4650199290c24a4d945ebe48cf889d0' },
|
||||
];
|
||||
|
||||
// A bytes32 string that represents some user data
|
||||
const secret = '0x0000000000000000000000000000000000000000000000000000000000123456';
|
||||
const hashedSecret = web3.utils.soliditySha3(identity.options.address, secret);
|
||||
|
||||
let threshold = 3;
|
||||
let friendHashes = [
|
||||
web3.utils.soliditySha3(identity.options.address, secret, friends[0].address),
|
||||
web3.utils.soliditySha3(identity.options.address, secret, friends[1].address),
|
||||
web3.utils.soliditySha3(identity.options.address, secret, friends[2].address),
|
||||
web3.utils.soliditySha3(identity.options.address, secret, friends[3].address),
|
||||
];
|
||||
|
||||
let newController = accounts[9];
|
||||
|
||||
let recovery = await recoveryContract.deploy({data: friendsRecoveryJson.code,
|
||||
arguments: [identity.options.address, 600, threshold, hashedSecret, friendHashes] })
|
||||
.send({from: accounts[0], gas: 5000000, gasPrice: 1});
|
||||
recovery.setProvider(web3.currentProvider);
|
||||
|
||||
// Setting up recovery contract for identity
|
||||
let tx1 = await identity.methods.execute(
|
||||
identity.options.address,
|
||||
0,
|
||||
idUtils.encode.setupRecovery(recovery.options.address))
|
||||
.send({from: accounts[0], gas: 5000000});
|
||||
|
||||
const newSecret = '0x0000000000000000000000000000000000000000000000000000000000abcdef';
|
||||
const data = idUtils.encode.managerReset(newController);
|
||||
const newHashedSecret = web3.utils.soliditySha3(identity.options.address, newSecret);
|
||||
const newFriendHashes = [
|
||||
web3.utils.soliditySha3(accounts[3], newSecret),
|
||||
web3.utils.soliditySha3(accounts[4], newSecret),
|
||||
web3.utils.soliditySha3(accounts[5], newSecret)
|
||||
];
|
||||
|
||||
// Normaly we would use soliditySha3, but it doesn't like arrays
|
||||
const hashedMessageToSign = await TestContract.methods.hash(identity.options.address, secret, identity.options.address, data, newHashedSecret, newFriendHashes).call();
|
||||
let msgHash = ethUtils.hashPersonalMessage(ethUtils.toBuffer(hashedMessageToSign, 'hex'));
|
||||
const friendSignatures = [
|
||||
ethUtils.ecsign(msgHash, ethUtils.toBuffer(friends[0].private, 'hex')),
|
||||
ethUtils.ecsign(msgHash, ethUtils.toBuffer(friends[1].private, 'hex')),
|
||||
ethUtils.ecsign(msgHash, ethUtils.toBuffer(friends[2].private, 'hex')),
|
||||
ethUtils.ecsign(msgHash, ethUtils.toBuffer(friends[3].private, 'hex'))
|
||||
];
|
||||
|
||||
let tx2 = await recovery.methods.approvePreSigned(
|
||||
hashedMessageToSign,
|
||||
[
|
||||
friendSignatures[0].v,
|
||||
friendSignatures[1].v,
|
||||
friendSignatures[2].v
|
||||
],
|
||||
[
|
||||
'0x' + friendSignatures[0].r.toString('hex'),
|
||||
'0x' + friendSignatures[1].r.toString('hex'),
|
||||
'0x' + friendSignatures[2].r.toString('hex')
|
||||
],
|
||||
[
|
||||
'0x' + friendSignatures[0].s.toString('hex'),
|
||||
'0x' + friendSignatures[1].s.toString('hex'),
|
||||
'0x' + friendSignatures[2].s.toString('hex')
|
||||
])
|
||||
.send({from: accounts[9], gas: 5000000});
|
||||
|
||||
|
||||
let tx3 = await recovery.methods.execute(
|
||||
secret,
|
||||
identity.options.address,
|
||||
data,
|
||||
[
|
||||
friends[0].address,
|
||||
friends[1].address,
|
||||
friends[2].address
|
||||
],
|
||||
newHashedSecret,
|
||||
newFriendHashes)
|
||||
.send({from: accounts[5], gas: 5000000});
|
||||
|
||||
await identity.methods.processManagerReset(0).send({from: accounts[0], gas: 5000000});
|
||||
|
||||
assert.equal(
|
||||
await identity.methods.getKeyPurpose(TestUtils.addressToBytes32(newController)).call(),
|
||||
idUtils.purposes.MANAGEMENT,
|
||||
identity.options.address + ".getKeyPurpose(" + newController + ") is not MANAGEMENT_KEY")
|
||||
|
||||
assert.equal(
|
||||
await identity.methods.getKeyPurpose(TestUtils.addressToBytes32(newController)).call(),
|
||||
idUtils.purposes.MANAGEMENT,
|
||||
identity.options.address+".getKeyPurpose("+newController+") is not correct")
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
392
test/identity.js
392
test/identity.js
@ -1,97 +1,107 @@
|
||||
|
||||
const assert = require('assert');
|
||||
const Embark = require('embark');
|
||||
let EmbarkSpec = Embark.initTests();
|
||||
let web3 = EmbarkSpec.web3;
|
||||
const TestUtils = require("../utils/testUtils.js");
|
||||
const web3EthAbi = require("web3-eth-abi");
|
||||
const idUtils = require('../utils/identityUtils.js');
|
||||
|
||||
const Identity = artifacts.require("./identity/Identity.sol");
|
||||
const TestContract = artifacts.require("./test/TestContract.sol");
|
||||
describe("Identity", function() {
|
||||
this.timeout(0);
|
||||
|
||||
contract('Identity', function(accounts) {
|
||||
let accounts;
|
||||
|
||||
let identity;
|
||||
beforeEach( function(done) {
|
||||
this.timeout(0);
|
||||
|
||||
EmbarkSpec = Embark.initTests();
|
||||
web3 = EmbarkSpec.web3;
|
||||
|
||||
beforeEach(async () => {
|
||||
identity = await Identity.new({from: accounts[0]})
|
||||
})
|
||||
EmbarkSpec.deployAll({
|
||||
"Identity": {},
|
||||
"TestContract": {}
|
||||
}, (_accounts) => {
|
||||
accounts = _accounts;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe("Identity()", () => {
|
||||
it("initialize with msg.sender as management key", async () => {
|
||||
assert.equal(
|
||||
await identity.getKeyPurpose(TestUtils.addressToBytes32(accounts[0])),
|
||||
await Identity.methods.getKeyPurpose(TestUtils.addressToBytes32(accounts[0])).call(),
|
||||
idUtils.purposes.MANAGEMENT,
|
||||
identity.address + ".getKeyPurpose("+accounts[0]+") is not MANAGEMENT_KEY")
|
||||
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.execute(
|
||||
identity.address,
|
||||
await Identity.methods.execute(
|
||||
Identity.address,
|
||||
0,
|
||||
idUtils.encode.addKey(accounts[1], idUtils.purposes.ACTION, idUtils.types.ADDRESS),
|
||||
{from: accounts[0]}
|
||||
);
|
||||
idUtils.encode.addKey(accounts[1], idUtils.purposes.ACTION, idUtils.types.ADDRESS)
|
||||
).send({from: accounts[0]});
|
||||
|
||||
assert.equal(
|
||||
await identity.getKeyPurpose(TestUtils.addressToBytes32(accounts[1])),
|
||||
await Identity.methods.getKeyPurpose(TestUtils.addressToBytes32(accounts[1])).call(),
|
||||
idUtils.purposes.ACTION,
|
||||
identity.address+".getKeyPurpose("+accounts[1]+") is not ACTION_KEY")
|
||||
Identity.address+".getKeyPurpose("+accounts[1]+") is not ACTION_KEY");
|
||||
});
|
||||
|
||||
it("should not add key by non manager", async () => {
|
||||
try {
|
||||
await identity.execute(
|
||||
identity.address,
|
||||
await Identity.methods.execute(
|
||||
Identity.address,
|
||||
0,
|
||||
idUtils.encode.addKey(accounts[1], idUtils.purposes.MANAGEMENT, idUtils.types.ADDRESS),
|
||||
{from: accounts[2]}
|
||||
);
|
||||
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.getKeyPurpose(TestUtils.addressToBytes32(accounts[1])),
|
||||
await Identity.methods.getKeyPurpose(TestUtils.addressToBytes32(accounts[1])).call(),
|
||||
idUtils.purposes.NONE,
|
||||
identity.address+".getKeyPurpose("+accounts[1]+") is not correct")
|
||||
Identity.address+".getKeyPurpose("+accounts[1]+") is not correct");
|
||||
|
||||
});
|
||||
|
||||
it("should not add key type 1 by actor", async () => {
|
||||
await identity.execute(
|
||||
identity.address,
|
||||
await Identity.methods.execute(
|
||||
Identity.address,
|
||||
0,
|
||||
idUtils.encode.addKey(accounts[2], idUtils.purposes.ACTION, idUtils.types.ADDRESS),
|
||||
{from: accounts[0]}
|
||||
);
|
||||
idUtils.encode.addKey(accounts[2], idUtils.purposes.ACTION, idUtils.types.ADDRESS))
|
||||
.send({from: accounts[0]});
|
||||
|
||||
try {
|
||||
await identity.execute(
|
||||
identity.address,
|
||||
await Identity.methods.execute(
|
||||
Identity.address,
|
||||
0,
|
||||
idUtils.encode.addKey(accounts[1], idUtils.purposes.MANAGEMENT, idUtils.types.ADDRESS),
|
||||
{from: accounts[2]}
|
||||
);
|
||||
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.getKeyPurpose(TestUtils.addressToBytes32(accounts[1])),
|
||||
await Identity.methods.getKeyPurpose(TestUtils.addressToBytes32(accounts[1])).call(),
|
||||
idUtils.purposes.NONE,
|
||||
identity.address+".getKeyType("+accounts[1]+") is not correct")
|
||||
Identity.address+".getKeyType("+accounts[1]+") is not correct");
|
||||
});
|
||||
|
||||
it("fire KeyAdded(address indexed key, uint256 indexed type)", async () => {
|
||||
await identity.execute(
|
||||
identity.address,
|
||||
let receipt = await Identity.methods.execute(
|
||||
Identity.address,
|
||||
0,
|
||||
idUtils.encode.addKey(accounts[1], idUtils.purposes.MANAGEMENT, idUtils.types.ADDRESS),
|
||||
{from: accounts[0]}
|
||||
);
|
||||
idUtils.encode.addKey(accounts[1], idUtils.purposes.MANAGEMENT, idUtils.types.ADDRESS))
|
||||
.send({from: accounts[0]});
|
||||
|
||||
const keyAdded = await TestUtils.listenForEvent(identity.KeyAdded())
|
||||
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")
|
||||
});
|
||||
@ -100,115 +110,106 @@ contract('Identity', function(accounts) {
|
||||
|
||||
describe("removeKey(address _key, uint256 _type)", () => {
|
||||
it("MANAGEMENT_KEY should remove a key", async () => {
|
||||
await identity.execute(
|
||||
identity.address,
|
||||
await Identity.methods.execute(
|
||||
Identity.address,
|
||||
0,
|
||||
idUtils.encode.addKey(accounts[1], idUtils.purposes.MANAGEMENT, idUtils.types.ADDRESS),
|
||||
{from: accounts[0]}
|
||||
);
|
||||
idUtils.encode.addKey(accounts[1], idUtils.purposes.MANAGEMENT, idUtils.types.ADDRESS))
|
||||
.send({from: accounts[0]});
|
||||
|
||||
await identity.execute(
|
||||
identity.address,
|
||||
await Identity.methods.execute(
|
||||
Identity.address,
|
||||
0,
|
||||
idUtils.encode.removeKey(accounts[1], idUtils.purposes.MANAGEMENT),
|
||||
{from: accounts[0]}
|
||||
);
|
||||
idUtils.encode.removeKey(accounts[1], idUtils.purposes.MANAGEMENT))
|
||||
.send({from: accounts[0]});
|
||||
|
||||
assert.equal(
|
||||
await identity.getKeyPurpose(TestUtils.addressToBytes32(accounts[1])),
|
||||
await Identity.methods.getKeyPurpose(TestUtils.addressToBytes32(accounts[1])).call(),
|
||||
idUtils.purposes.NONE,
|
||||
identity.address+".getKeyPurpose("+accounts[1]+") is not 0")
|
||||
Identity.address+".getKeyPurpose("+accounts[1]+") is not 0")
|
||||
});
|
||||
|
||||
it("other key should not remove a key", async () => {
|
||||
await identity.execute(
|
||||
identity.address,
|
||||
await Identity.methods.execute(
|
||||
Identity.address,
|
||||
0,
|
||||
idUtils.encode.addKey(accounts[1], idUtils.purposes.MANAGEMENT, idUtils.types.ADDRESS),
|
||||
{from: accounts[0]}
|
||||
);
|
||||
idUtils.encode.addKey(accounts[1], idUtils.purposes.MANAGEMENT, idUtils.types.ADDRESS))
|
||||
.send({from: accounts[0]});
|
||||
|
||||
try {
|
||||
await identity.execute(
|
||||
identity.address,
|
||||
await Identity.methods.execute(
|
||||
Identity.address,
|
||||
0,
|
||||
idUtils.encode.removeKey(accounts[1], idUtils.purposes.MANAGEMENT),
|
||||
{from: accounts[2]}
|
||||
);
|
||||
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.getKeyPurpose(TestUtils.addressToBytes32(accounts[1])),
|
||||
await Identity.methods.getKeyPurpose(TestUtils.addressToBytes32(accounts[1])).call(),
|
||||
idUtils.purposes.MANAGEMENT,
|
||||
identity.address+".getKeyPurpose("+accounts[1]+") is not 0")
|
||||
Identity.address+".getKeyPurpose("+accounts[1]+") is not 0")
|
||||
});
|
||||
|
||||
it("actor key should not remove key", async () => {
|
||||
await identity.execute(
|
||||
identity.address,
|
||||
await Identity.methods.execute(
|
||||
Identity.address,
|
||||
0,
|
||||
idUtils.encode.addKey(accounts[1], idUtils.purposes.ACTION, idUtils.types.ADDRESS),
|
||||
{from: accounts[0]}
|
||||
);
|
||||
idUtils.encode.addKey(accounts[1], idUtils.purposes.ACTION, idUtils.types.ADDRESS))
|
||||
.send({from: accounts[0]});
|
||||
|
||||
await identity.execute(
|
||||
identity.address,
|
||||
await Identity.methods.execute(
|
||||
Identity.address,
|
||||
0,
|
||||
idUtils.encode.addKey(accounts[2], idUtils.purposes.ACTION, idUtils.types.ADDRESS),
|
||||
{from: accounts[0]}
|
||||
);
|
||||
idUtils.encode.addKey(accounts[2], idUtils.purposes.ACTION, idUtils.types.ADDRESS))
|
||||
.send({from: accounts[0]});
|
||||
|
||||
try {
|
||||
await identity.execute(
|
||||
identity.address,
|
||||
await Identity.methods.execute(
|
||||
Identity.address,
|
||||
0,
|
||||
idUtils.encode.removeKey(accounts[1], idUtils.purposes.ACTION),
|
||||
{from: accounts[2]}
|
||||
);
|
||||
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.getKeyPurpose(TestUtils.addressToBytes32(accounts[1])),
|
||||
await Identity.methods.getKeyPurpose(TestUtils.addressToBytes32(accounts[1])).call(),
|
||||
idUtils.purposes.ACTION,
|
||||
identity.address+".getKeyType("+accounts[1]+") is not 0")
|
||||
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.execute(
|
||||
identity.address,
|
||||
await Identity.methods.execute(
|
||||
Identity.address,
|
||||
0,
|
||||
idUtils.encode.removeKey(accounts[0], idUtils.purposes.MANAGEMENT),
|
||||
{from: accounts[0]}
|
||||
);
|
||||
idUtils.encode.removeKey(accounts[0], idUtils.purposes.MANAGEMENT))
|
||||
.send({from: accounts[0]});
|
||||
|
||||
assert.equal(
|
||||
await identity.getKeyPurpose(TestUtils.addressToBytes32(accounts[0])),
|
||||
await Identity.methods.getKeyPurpose(TestUtils.addressToBytes32(accounts[0])).call(),
|
||||
idUtils.purposes.MANAGEMENT,
|
||||
identity.address+".getKeyType("+accounts[0]+") is not 1")
|
||||
Identity.address+".getKeyType("+accounts[0]+") is not 1")
|
||||
});
|
||||
|
||||
it("fire KeyRemoved(address indexed key, uint256 indexed type)", async () => {
|
||||
await identity.execute(
|
||||
identity.address,
|
||||
await Identity.methods.execute(
|
||||
Identity.address,
|
||||
0,
|
||||
idUtils.encode.addKey(accounts[1], idUtils.purposes.ACTION, idUtils.types.ADDRESS),
|
||||
{from: accounts[0]}
|
||||
);
|
||||
idUtils.encode.addKey(accounts[1], idUtils.purposes.ACTION, idUtils.types.ADDRESS))
|
||||
.send({from: accounts[0]});
|
||||
|
||||
await identity.execute(
|
||||
identity.address,
|
||||
let receipt = await Identity.methods.execute(
|
||||
Identity.address,
|
||||
0,
|
||||
idUtils.encode.removeKey(accounts[1], idUtils.purposes.ACTION),
|
||||
{from: accounts[0]}
|
||||
);
|
||||
idUtils.encode.removeKey(accounts[1], idUtils.purposes.ACTION))
|
||||
.send({from: accounts[0]});
|
||||
|
||||
const keyRemoved = await TestUtils.listenForEvent(identity.KeyRemoved());
|
||||
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");
|
||||
});
|
||||
@ -219,42 +220,40 @@ contract('Identity', function(accounts) {
|
||||
|
||||
it("should start only with initializer as only key", async () => {
|
||||
assert.equal(
|
||||
await identity.getKeyPurpose(TestUtils.addressToBytes32(accounts[0])),
|
||||
await Identity.methods.getKeyPurpose(TestUtils.addressToBytes32(accounts[0])).call(),
|
||||
idUtils.purposes.MANAGEMENT,
|
||||
identity.address+".getKeyPurpose("+accounts[0]+") is not correct")
|
||||
Identity.address+".getKeyPurpose("+accounts[0]+") is not correct")
|
||||
|
||||
assert.equal(
|
||||
await identity.getKeyPurpose(TestUtils.addressToBytes32(accounts[1])),
|
||||
await Identity.methods.getKeyPurpose(TestUtils.addressToBytes32(accounts[1])).call(),
|
||||
idUtils.purposes.NONE,
|
||||
identity.address+".getKeyPurpose("+accounts[1]+") is not correct")
|
||||
Identity.address+".getKeyPurpose("+accounts[1]+") is not correct")
|
||||
});
|
||||
|
||||
it("should get type 2 after addKey type 2", async () => {
|
||||
await identity.execute(
|
||||
identity.address,
|
||||
await Identity.methods.execute(
|
||||
Identity.address,
|
||||
0,
|
||||
idUtils.encode.addKey(accounts[1], idUtils.purposes.ACTION, idUtils.types.ADDRESS),
|
||||
{from: accounts[0]}
|
||||
);
|
||||
idUtils.encode.addKey(accounts[1], idUtils.purposes.ACTION, idUtils.types.ADDRESS))
|
||||
.send({from: accounts[0]});
|
||||
|
||||
assert.equal(
|
||||
await identity.getKeyPurpose(TestUtils.addressToBytes32(accounts[1])),
|
||||
await Identity.methods.getKeyPurpose(TestUtils.addressToBytes32(accounts[1])).call(),
|
||||
idUtils.purposes.ACTION,
|
||||
identity.address+".getKeyPurpose("+accounts[1]+") is not correct")
|
||||
Identity.address+".getKeyPurpose("+accounts[1]+") is not correct")
|
||||
});
|
||||
|
||||
it("should get type 3 after addKey type 3", async () => {
|
||||
await identity.execute(
|
||||
identity.address,
|
||||
await Identity.methods.execute(
|
||||
Identity.address,
|
||||
0,
|
||||
idUtils.encode.addKey(accounts[1], idUtils.purposes.CLAIM_SIGNER, idUtils.types.ADDRESS),
|
||||
{from: accounts[0]}
|
||||
);
|
||||
idUtils.encode.addKey(accounts[1], idUtils.purposes.CLAIM_SIGNER, idUtils.types.ADDRESS))
|
||||
.send({from: accounts[0]});
|
||||
|
||||
assert.equal(
|
||||
await identity.getKeyPurpose(TestUtils.addressToBytes32(accounts[1])),
|
||||
await Identity.methods.getKeyPurpose(TestUtils.addressToBytes32(accounts[1])).call(),
|
||||
idUtils.purposes.CLAIM_SIGNER,
|
||||
identity.address+".getKeyPurpose("+accounts[1]+") is not correct")
|
||||
Identity.address+".getKeyPurpose("+accounts[1]+") is not correct")
|
||||
});
|
||||
|
||||
});
|
||||
@ -274,63 +273,60 @@ contract('Identity', function(accounts) {
|
||||
|
||||
});
|
||||
});
|
||||
*/
|
||||
|
||||
*/
|
||||
|
||||
describe("execute(address _to, uint256 _value, bytes _data)", () => {
|
||||
let testContractInstance;
|
||||
let functionPayload;
|
||||
|
||||
it("Identity should receive ether", async() => {
|
||||
|
||||
const amountToSend = web3.toWei(0.05, "ether");
|
||||
const amountToSend = web3.utils.toWei('0.05', "ether");
|
||||
|
||||
let idBalance0 = web3.eth.getBalance(identity.address);
|
||||
let idBalance0 = await web3.eth.getBalance(Identity.address);
|
||||
|
||||
await web3.eth.sendTransaction({from:accounts[0], to:identity.address, value: amountToSend})
|
||||
await web3.eth.sendTransaction({from:accounts[0], to:Identity.address, value: amountToSend})
|
||||
|
||||
let idBalance1 = web3.eth.getBalance(identity.address);
|
||||
let idBalance1 = await web3.eth.getBalance(Identity.address);
|
||||
|
||||
assert.equal(idBalance0.toNumber() + amountToSend, idBalance1.toNumber(), identity.address + " did not receive ether");
|
||||
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.execute(
|
||||
identity.address,
|
||||
await Identity.methods.execute(
|
||||
Identity.address,
|
||||
0,
|
||||
idUtils.encode.addKey(accounts[1], idUtils.purposes.ACTION, idUtils.types.ADDRESS),
|
||||
{from: accounts[0]}
|
||||
);
|
||||
idUtils.encode.addKey(accounts[1], idUtils.purposes.ACTION, idUtils.types.ADDRESS))
|
||||
.send({from: accounts[0]});
|
||||
|
||||
testContractInstance = await TestContract.new({from: accounts[0]});
|
||||
|
||||
functionPayload = web3EthAbi.encodeFunctionCall({
|
||||
|
||||
functionPayload = web3.eth.abi.encodeFunctionCall({
|
||||
name: 'test',
|
||||
type: 'function',
|
||||
inputs: []
|
||||
}, []);
|
||||
|
||||
await identity.execute(
|
||||
testContractInstance.address,
|
||||
let receipt = await Identity.methods.execute(
|
||||
TestContract.address,
|
||||
0,
|
||||
functionPayload,
|
||||
{from: accounts[1]}
|
||||
);
|
||||
|
||||
assert.notEqual(
|
||||
await TestUtils.listenForEvent(testContractInstance.TestFunctionExecuted()),
|
||||
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");
|
||||
"Test function was not executed"); */
|
||||
|
||||
});
|
||||
|
||||
it("MANAGEMENT_KEY cannot execute arbitrary transaction", async () => {
|
||||
try {
|
||||
await identity.execute(
|
||||
testContractInstance.address,
|
||||
await Identity.methods.execute(
|
||||
TestContract.address,
|
||||
0,
|
||||
functionPayload,
|
||||
{from: accounts[0]}
|
||||
);
|
||||
functionPayload)
|
||||
.send({from: accounts[0]});
|
||||
} catch(error) {
|
||||
TestUtils.assertJump(error);
|
||||
}
|
||||
@ -338,12 +334,11 @@ contract('Identity', function(accounts) {
|
||||
|
||||
it("Other keys NOT execute arbitrary transaction", async () => {
|
||||
try {
|
||||
await identity.execute(
|
||||
testContractInstance.address,
|
||||
await Identity.methods.execute(
|
||||
TestContract.address,
|
||||
0,
|
||||
functionPayload,
|
||||
{from: accounts[3]}
|
||||
);
|
||||
functionPayload)
|
||||
.send({from: accounts[3]});
|
||||
assert.fail('should have reverted before');
|
||||
} catch(error) {
|
||||
TestUtils.assertJump(error);
|
||||
@ -352,82 +347,74 @@ contract('Identity', function(accounts) {
|
||||
|
||||
|
||||
it("ACTION_KEY should send ether from contract", async () => {
|
||||
await identity.execute(
|
||||
identity.address,
|
||||
await Identity.methods.execute(
|
||||
Identity.address,
|
||||
0,
|
||||
idUtils.encode.addKey(accounts[1], idUtils.purposes.ACTION, idUtils.types.ADDRESS),
|
||||
{from: accounts[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.toWei(0.05, "ether")})
|
||||
await web3.eth.sendTransaction({from:accounts[0], to:Identity.address, value: web3.utils.toWei('0.05', "ether")})
|
||||
|
||||
const amountToSend = web3.toWei(0.01, "ether");
|
||||
const amountToSend = web3.utils.toWei('0.01', "ether");
|
||||
|
||||
let idBalance0 = web3.eth.getBalance(identity.address);
|
||||
let a2Balance0 = web3.eth.getBalance(accounts[2]);
|
||||
let idBalance0 = await web3.eth.getBalance(Identity.address);
|
||||
let a2Balance0 = await web3.eth.getBalance(accounts[2]);
|
||||
|
||||
await identity.execute(
|
||||
await Identity.methods.execute(
|
||||
accounts[2],
|
||||
amountToSend,
|
||||
'',
|
||||
{from: accounts[1]}
|
||||
);
|
||||
'0x')
|
||||
.send({from: accounts[1]});
|
||||
|
||||
let idBalance1 = web3.eth.getBalance(identity.address);
|
||||
let a2Balance1 = web3.eth.getBalance(accounts[2]);
|
||||
let idBalance1 = await web3.eth.getBalance(Identity.address);
|
||||
let a2Balance1 = await web3.eth.getBalance(accounts[2]);
|
||||
|
||||
assert(idBalance1.toNumber, idBalance0.toNumber - amountToSend, "Contract did not send ether");
|
||||
assert(a2Balance1.toNumber, a2Balance0.toNumber + amountToSend, accounts[2] + " did not receive ether");
|
||||
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.execute(
|
||||
identity.address,
|
||||
await Identity.methods.execute(
|
||||
Identity.address,
|
||||
0,
|
||||
idUtils.encode.addKey(accounts[1], idUtils.purposes.ACTION, idUtils.types.ADDRESS),
|
||||
{from: accounts[0]}
|
||||
);
|
||||
idUtils.encode.addKey(accounts[1], idUtils.purposes.ACTION, idUtils.types.ADDRESS))
|
||||
.send({from: accounts[0]});
|
||||
|
||||
await identity.execute(
|
||||
testContractInstance.address,
|
||||
let receipt = await Identity.methods.execute(
|
||||
TestContract.address,
|
||||
0,
|
||||
functionPayload,
|
||||
{from: accounts[1]}
|
||||
);
|
||||
|
||||
const executionRequested = await TestUtils.listenForEvent(identity.ExecutionRequested());
|
||||
assert(executionRequested.to, testContractInstance.address, "To is not correct");
|
||||
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.execute(
|
||||
identity.address,
|
||||
await Identity.methods.execute(
|
||||
Identity.address,
|
||||
0,
|
||||
idUtils.encode.addKey(accounts[1], idUtils.purposes.ACTION, idUtils.types.ADDRESS),
|
||||
{from: accounts[0]}
|
||||
);
|
||||
idUtils.encode.addKey(accounts[1], idUtils.purposes.ACTION, idUtils.types.ADDRESS))
|
||||
.send({from: accounts[0]});
|
||||
|
||||
await identity.execute(
|
||||
testContractInstance.address,
|
||||
let receipt = await Identity.methods.execute(
|
||||
TestContract.address,
|
||||
0,
|
||||
functionPayload,
|
||||
{from: accounts[1]}
|
||||
);
|
||||
functionPayload)
|
||||
.send({from: accounts[1]});
|
||||
|
||||
const executed = await TestUtils.listenForEvent(identity.Executed());
|
||||
assert(executed.to, testContractInstance.address, "To is not correct");
|
||||
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 () => {
|
||||
|
||||
@ -501,5 +488,10 @@ contract('Identity', function(accounts) {
|
||||
|
||||
});
|
||||
});
|
||||
*/
|
||||
*/
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
@ -1,3 +1,6 @@
|
||||
/*
|
||||
COMMENTED TEMPORARLY WHILE PROJECT IS MIGRATED TO EMBARK - @rramos
|
||||
|
||||
const TestUtils = require("../utils/testUtils.js")
|
||||
var ethUtils = require('ethereumjs-util')
|
||||
|
||||
@ -62,3 +65,4 @@ contract('Identity - Extended Functionality', function(accounts) {
|
||||
|
||||
|
||||
});
|
||||
*/
|
@ -1,9 +0,0 @@
|
||||
module.exports = {
|
||||
networks: {
|
||||
development: {
|
||||
host: "localhost",
|
||||
port: 8540,
|
||||
network_id: "*" // Match any network id
|
||||
}
|
||||
}
|
||||
};
|
@ -117,7 +117,6 @@ const _managerReset = function(address){
|
||||
}, [address]);
|
||||
}
|
||||
|
||||
|
||||
const _updateUpdatableInstance = function(address){
|
||||
if(!/^(0x)?[0-9a-f]{0,40}$/i.test(address))
|
||||
throw new Error('Address "'+ address +'" is not a valid Ethereum address.');
|
||||
|
@ -23,7 +23,7 @@ exports.assertReverts = (contractMethodCall, maxGasAvailable) => {
|
||||
}
|
||||
|
||||
exports.listenForEvent = event => new Promise((resolve, reject) => {
|
||||
event.watch((error, response) => {
|
||||
event({}, (error, response) => {
|
||||
if (!error) {
|
||||
resolve(response.args)
|
||||
} else {
|
||||
@ -31,8 +31,12 @@ exports.listenForEvent = event => new Promise((resolve, reject) => {
|
||||
}
|
||||
event.stopWatching()
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
exports.eventValues = (receipt, eventName) => {
|
||||
if(receipt.events[eventName])
|
||||
return receipt.events[eventName].returnValues;
|
||||
}
|
||||
|
||||
exports.addressToBytes32 = (address) => {
|
||||
const stringed = "0000000000000000000000000000000000000000000000000000000000000000" + address.slice(2);
|
||||
@ -67,5 +71,27 @@ exports.expectThrow = async promise => {
|
||||
|
||||
|
||||
exports.assertJump = (error) => {
|
||||
assert.isAbove(error.message.search('revert'), -1, 'Revert should happen');
|
||||
}
|
||||
assert(error.message.search('revert') > -1, 'Revert should happen');
|
||||
}
|
||||
|
||||
|
||||
var callbackToResolve = function (resolve, reject) {
|
||||
return function (error, value) {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(value);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
exports.promisify = (func) =>
|
||||
(...args) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const callback = (err, data) => err ? reject(err) : resolve(data);
|
||||
func.apply(this, [...args, callback]);
|
||||
});
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user