From 9deb9ca25bcae4e16d4ecdd177eb745ae82d34c5 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Thu, 11 Oct 2018 16:52:24 +0200 Subject: [PATCH 01/15] functions for signed transfer manager --- .../TransferManager/SignedTransferManager.sol | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 contracts/modules/TransferManager/SignedTransferManager.sol diff --git a/contracts/modules/TransferManager/SignedTransferManager.sol b/contracts/modules/TransferManager/SignedTransferManager.sol new file mode 100644 index 000000000..136a66444 --- /dev/null +++ b/contracts/modules/TransferManager/SignedTransferManager.sol @@ -0,0 +1,108 @@ +pragma solidity ^0.4.24; + +import "./ITransferManager.sol"; +import "openzeppelin-solidity/contracts/math/SafeMath.sol"; + +/** + * @title Transfer Manager module for verifing transations with a signed message + */ +contract SignedTransferManager is ITransferManager { + using SafeMath for uint256; + + bytes32 constant public ADMIN = "ADMIN"; + + //Keeps track of if the signature has been used or invalidated + mapping (bytes => bool) public invalidSignatures; + + //keep tracks of the address that allows to sign messages + mapping (address => bool) public signers; + + + event AddManualApproval( + address _from, + address _to, + uint256 _allowance, + uint256 _expiryTime, + address _addedBy + ); + + + /** + * @notice Constructor + * @param _securityToken Address of the security token + * @param _polyAddress Address of the polytoken + */ + constructor (address _securityToken, address _polyAddress) + public + Module(_securityToken, _polyAddress) + { + } + + /** + * @notice This function returns the signature of configure function + */ + function getInitFunction() public pure returns (bytes4) { + return bytes4(0); + } + + function updateSigners(address[] _signers, bool[] _signersStats) public withPerm(ADMIN) { + require(_signers.length == _signersStats.length, "input array length does not match"); + for(i=0; i<_signers.length; i++){ + signers[address[i]] = _signersStats[i]; + } + } + + /** + * @notice default implementation of verifyTransfer used by SecurityToken + * If the transfer request comes from the STO, it only checks that the investor is in the whitelist + * If the transfer request comes from a token holder, it checks that: + * a) Both are on the whitelist + * b) Seller's sale lockup period is over + * c) Buyer's purchase lockup is over + */ + function verifyTransfer(address _from, address _to, uint256 _amount, bytes _data , bool _isTransfer, uint8 _v, bytes32 _r, bytes32 _s) public returns(Result) { + if (!paused) { + + require(invalidSignatures[_data] != true, "Invalide signature - signature is either used or deemed as invalid"); + + address memory signer = ecrecover(_data, _v, _r, _s); + require(signers[signer] == true, "Invalid signature - signer not authroized."); + + bytes32 hash = keccak256(abi.encodePacked(this, _from, _to, _amount)); + _checkSig(hash, _v, _r, _s); + + if(_isTransfer == true){ + invalidSignatures[_data] = true; + return Result.VALID; + } + return Result.VALID; + } + return Result.NA; + } + + function invalideSignature(bytes _data) public { + require(signers[msg.sender] == true, "Only signer is allowed to invalide signature."); + require(invalidSignatures[_data] != true, "This signature is already invalid."); + invalidSignatures[_data] != true; + } + + /** + * @notice used to verify the signature + */ + function _checkSig(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) internal view { + //Check that the signature is valid + //sig should be signing - _investor, _fromTime, _toTime & _expiryTime and be signed by the issuer address + address signer = ecrecover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _hash)), _v, _r, _s); + require(signer == Ownable(securityToken).owner() || signer == signingAddress, "Incorrect signer"); + } + + + /** + * @notice Return the permissions flag that are associated with ManualApproval transfer manager + */ + function getPermissions() public view returns(bytes32[]) { + bytes32[] memory allPermissions = new bytes32[](1); + allPermissions[0] = TRANSFER_APPROVAL; + return allPermissions; + } +} From a5d94549bdb383b3c77e391acd70b80048edf2d9 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Tue, 16 Oct 2018 14:08:26 +0200 Subject: [PATCH 02/15] solidity hashing issues --- .eslintrc.js | 5 +- .../TransferManager/SignedTransferManager.sol | 79 +++-- .../SignedTransferManagerFactory.sol | 102 ++++++ test/helpers/createInstances.js | 16 + test/helpers/signData.js | 36 +- test/y_signed_transfer_manager.js | 308 ++++++++++++++++++ 6 files changed, 516 insertions(+), 30 deletions(-) create mode 100644 contracts/modules/TransferManager/SignedTransferManagerFactory.sol create mode 100644 test/y_signed_transfer_manager.js diff --git a/.eslintrc.js b/.eslintrc.js index 463539deb..0209e7387 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -14,6 +14,9 @@ module.exports = { "quotes": 0, "semi": 0, "no-undef": 0, - "key-spacing": 0 + "key-spacing": 0, + "node":0, + "spaced-comment":0, + "node/no-deprecated-api":0 } }; diff --git a/contracts/modules/TransferManager/SignedTransferManager.sol b/contracts/modules/TransferManager/SignedTransferManager.sol index 136a66444..6a4ea9563 100644 --- a/contracts/modules/TransferManager/SignedTransferManager.sol +++ b/contracts/modules/TransferManager/SignedTransferManager.sol @@ -12,19 +12,16 @@ contract SignedTransferManager is ITransferManager { bytes32 constant public ADMIN = "ADMIN"; //Keeps track of if the signature has been used or invalidated - mapping (bytes => bool) public invalidSignatures; + mapping(bytes => bool) invalidSignatures; //keep tracks of the address that allows to sign messages - mapping (address => bool) public signers; + mapping(address => bool) public signers; - event AddManualApproval( - address _from, - address _to, - uint256 _allowance, - uint256 _expiryTime, - address _addedBy - ); + // Emit when signer stats was changed + event UpdateSigners(address[] _signers, bool[] _signersStats); + // Emit when there is change in the flag variable called allowAllTransfers + event InvalidSignature(bytes _data); /** @@ -45,11 +42,16 @@ contract SignedTransferManager is ITransferManager { return bytes4(0); } + function checkSignatureIsInvalid(bytes _data) public view returns(bool){ + return invalidSignatures[_data]; + } + function updateSigners(address[] _signers, bool[] _signersStats) public withPerm(ADMIN) { require(_signers.length == _signersStats.length, "input array length does not match"); - for(i=0; i<_signers.length; i++){ - signers[address[i]] = _signersStats[i]; + for(uint8 i=0; i<_signers.length; i++){ + signers[_signers[i]] = _signersStats[i]; } + emit UpdateSigners(_signers, _signersStats); } /** @@ -60,40 +62,63 @@ contract SignedTransferManager is ITransferManager { * b) Seller's sale lockup period is over * c) Buyer's purchase lockup is over */ - function verifyTransfer(address _from, address _to, uint256 _amount, bytes _data , bool _isTransfer, uint8 _v, bytes32 _r, bytes32 _s) public returns(Result) { + function verifyTransfer(address _from, address _to, uint256 _amount, bytes _data , bool _isTransfer) public returns(Result) { if (!paused) { - require(invalidSignatures[_data] != true, "Invalide signature - signature is either used or deemed as invalid"); - - address memory signer = ecrecover(_data, _v, _r, _s); - require(signers[signer] == true, "Invalid signature - signer not authroized."); + require(invalidSignatures[_data] != true, "Invalid signature - signature is either used or deemed as invalid"); bytes32 hash = keccak256(abi.encodePacked(this, _from, _to, _amount)); - _checkSig(hash, _v, _r, _s); + address signer = _recoverSignerAdd(hash, _data); + require(signers[signer] == true, "Invalid signature - signer is not on the list"); if(_isTransfer == true){ invalidSignatures[_data] = true; - return Result.VALID; } + return Result.VALID; } return Result.NA; } - function invalideSignature(bytes _data) public { - require(signers[msg.sender] == true, "Only signer is allowed to invalide signature."); - require(invalidSignatures[_data] != true, "This signature is already invalid."); - invalidSignatures[_data] != true; + function invalidSignature(address _from, address _to, uint256 _amount, bytes _data, bytes32 _hash) public view returns(address) { + require(signers[msg.sender] == true, "Only signer is allowed to invalid signature."); + require(invalidSignatures[_data] != true, "This signature is invalid."); + + // bytes32 _hash = keccak256(abi.encodePacked(this, _from, _to, _amount)); + + address signer = _recoverSignerAdd(_hash,_data); + return signer; + // require(signer == msg.sender, "Incorrect Signer for this signature"); + + // invalidSignatures[_data] = true; + // emit InvalidSignature(_data); } /** * @notice used to verify the signature */ - function _checkSig(bytes32 _hash, uint8 _v, bytes32 _r, bytes32 _s) internal view { + function _recoverSignerAdd(bytes32 _hash, bytes _data) internal view returns(address) { + //Check that the signature is valid - //sig should be signing - _investor, _fromTime, _toTime & _expiryTime and be signed by the issuer address - address signer = ecrecover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _hash)), _v, _r, _s); - require(signer == Ownable(securityToken).owner() || signer == signingAddress, "Incorrect signer"); + require(_data.length == 65, "Date input length is invalid"); + + bytes32 r; + bytes32 s; + uint8 v; + + assembly { + r := mload(add(_data, 32)) + s := mload(add(_data, 64)) + v := and(mload(add(_data, 65)), 255) + } + if (v < 27) { + v += 27; + } + if (v != 27 && v != 28) { + return 0; + } + + return ecrecover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _hash)), v, r, s); } @@ -102,7 +127,7 @@ contract SignedTransferManager is ITransferManager { */ function getPermissions() public view returns(bytes32[]) { bytes32[] memory allPermissions = new bytes32[](1); - allPermissions[0] = TRANSFER_APPROVAL; + allPermissions[0] = ADMIN; return allPermissions; } } diff --git a/contracts/modules/TransferManager/SignedTransferManagerFactory.sol b/contracts/modules/TransferManager/SignedTransferManagerFactory.sol new file mode 100644 index 000000000..da2bfd4b4 --- /dev/null +++ b/contracts/modules/TransferManager/SignedTransferManagerFactory.sol @@ -0,0 +1,102 @@ +pragma solidity ^0.4.24; + +import "./SignedTransferManager.sol"; +import "../ModuleFactory.sol"; + +/** + * @title Factory for deploying SignedTransferManager module + */ +contract SignedTransferManagerFactory is ModuleFactory { + + /** + * @notice Constructor + * @param _polyAddress Address of the polytoken + */ + constructor (address _polyAddress, uint256 _setupCost, uint256 _usageCost, uint256 _subscriptionCost) public + ModuleFactory(_polyAddress, _setupCost, _usageCost, _subscriptionCost) + { + version = "1.0.0"; + name = "SignedTransferManager"; + title = "Signed Transfer Manager"; + description = "Manage transfers using a signature"; + compatibleSTVersionRange["lowerBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + compatibleSTVersionRange["upperBound"] = VersionUtils.pack(uint8(0), uint8(0), uint8(0)); + } + + + /** + * @notice used to launch the Module with the help of factory + * @return address Contract address of the Module + */ + function deploy(bytes /* _data */) external returns(address) { + if (setupCost > 0) + require(polyToken.transferFrom(msg.sender, owner, setupCost), "Failed transferFrom because of sufficent Allowance is not provided"); + address signedTransferManager = new SignedTransferManager(msg.sender, address(polyToken)); + emit GenerateModuleFromFactory(address(signedTransferManager), getName(), address(this), msg.sender, setupCost, now); + return address(signedTransferManager); + } + + + /** + * @notice Type of the Module factory + */ + function getTypes() external view returns(uint8[]) { + uint8[] memory res = new uint8[](1); + res[0] = 2; + return res; + } + + /** + * @notice Get the name of the Module + */ + function getName() public view returns(bytes32) { + return name; + } + + /** + * @notice Get the description of the Module + */ + function getDescription() external view returns(string) { + return description; + } + + /** + * @notice Get the version of the Module + */ + function getVersion() external view returns(string) { + return version; + } + + /** + * @notice Get the title of the Module + */ + function getTitle() external view returns(string) { + return title; + } + + /** + * @notice Get the setup cost of the module + */ + function getSetupCost() external view returns (uint256) { + return setupCost; + } + + /** + * @notice Get the Instructions that helped to used the module + */ + function getInstructions() external view returns(string) { + return "Allows an issuer to maintain a list of signers who can validate transfer request using signatures. A mapping is used to track valid signers which can be managed by the issuer. verifytransfer function takes in a signature and if the signature is valid, it will verify the transfer. invalidSigature function allow the signer to make a signature invalid after it is signed. Init function takes no parameters."; + } + + /** + * @notice Get the tags related to the module factory + */ + function getTags() public view returns(bytes32[]) { + bytes32[] memory availableTags = new bytes32[](2); + availableTags[0] = "General"; + availableTags[1] = "Transfer Restriction"; + return availableTags; + } + + +} diff --git a/test/helpers/createInstances.js b/test/helpers/createInstances.js index ff2a66f4b..929babc1f 100644 --- a/test/helpers/createInstances.js +++ b/test/helpers/createInstances.js @@ -27,6 +27,8 @@ const PreSaleSTOFactory = artifacts.require("./PreSaleSTOFactory.sol"); const PolyToken = artifacts.require("./PolyToken.sol"); const PolyTokenFaucet = artifacts.require("./PolyTokenFaucet.sol"); const DummySTOFactory = artifacts.require("./DummySTOFactory.sol"); +const SignedTransferManagerFactory = artifacts.require("./SignedTransferManagerFactory"); + const Web3 = require("web3"); const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port @@ -59,6 +61,8 @@ let I_PolymathRegistry; let I_SecurityTokenRegistryProxy; let I_STRProxied; let I_MRProxied; +let I_SignedTransferManagerFactory; + // Initial fee for ticker registry and security token registry const initRegFee = web3.utils.toWei("250"); @@ -261,6 +265,18 @@ export async function deploySingleTradeVolumeRMAndVerified(accountPolymath, MRPr return new Array(I_SingleTradeVolumeRestrictionManagerFactory); } +export async function deploySignedTMAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { + I_SignedTransferManagerFactory = await SignedTransferManagerFactory.new(polyToken, setupCost, 0, 0, { from: accountPolymath }); + assert.notEqual( + I_SignedTransferManagerFactory.address.valueOf(), + "0x0000000000000000000000000000000000000000", + "SignedTransferManagerFactory contract was not deployed" + ); + + await registerAndVerifyByMR(I_SignedTransferManagerFactory.address, accountPolymath, MRProxyInstance); + return new Array(I_SignedTransferManagerFactory); +} + /// Deploy the Permission Manager export async function deployGPMAndVerifyed(accountPolymath, MRProxyInstance, polyToken, setupCost) { diff --git a/test/helpers/signData.js b/test/helpers/signData.js index 9d8b33380..bed34d91f 100644 --- a/test/helpers/signData.js +++ b/test/helpers/signData.js @@ -3,7 +3,7 @@ const utils = ethers.utils; const ethUtil = require("ethereumjs-util"); //this, _investor, _fromTime, _toTime, _validTo -function signData(tmAddress, investorAddress, fromTime, toTime, expiryTime, restricted, validFrom, validTo, pk) { +function signData (tmAddress, investorAddress, fromTime, toTime, expiryTime, restricted, validFrom, validTo, pk) { let packedData = utils .solidityKeccak256( ["address", "address", "uint256", "uint256", "uint256", "bool", "uint256", "uint256"], @@ -16,6 +16,38 @@ function signData(tmAddress, investorAddress, fromTime, toTime, expiryTime, rest return ethUtil.ecsign(new Buffer(packedData.slice(2), "hex"), new Buffer(pk, "hex")); } +// sign data for verify tranfer function +function signDataVerifyTransfer (tmAddress, fromAddress, toAddress, amount, account) { + let packedData = utils + .solidityKeccak256( + ["address", "address", "address", "uint256"], + [tmAddress, fromAddress, toAddress, amount] + ) + .slice(2); + packedData = new Buffer(packedData, "hex"); + packedData = Buffer.concat([new Buffer(`\x19Ethereum Signed Message:\n${packedData.length.toString()}`), packedData]); + packedData = web3.sha3(`0x${packedData.toString("hex")}`, { encoding: "hex" }); + + return web3.eth.sign(account, packedData); + +} + +// test only for hashing +function hashedData (tmAddress, fromAddress, toAddress, amount) { + let packedData = utils + .solidityKeccak256( + ["address", "address", "address", "uint256"], + [tmAddress, fromAddress, toAddress, amount] + ) + .slice(2); + packedData = new Buffer(packedData, "hex"); + packedData = Buffer.concat([new Buffer(`\x19Ethereum Signed Message:\n${packedData.length.toString()}`), packedData]); + packedData = web3.sha3(`0x${packedData.toString("hex")}`, { encoding: "hex" }); + + return packedData; + +} + module.exports = { - signData + signData, signDataVerifyTransfer, hashedData }; diff --git a/test/y_signed_transfer_manager.js b/test/y_signed_transfer_manager.js new file mode 100644 index 000000000..00e49e880 --- /dev/null +++ b/test/y_signed_transfer_manager.js @@ -0,0 +1,308 @@ +import latestTime from "./helpers/latestTime"; +import { duration, promisifyLogWatch, latestBlock } from "./helpers/utils"; +import takeSnapshot, { increaseTime, revertToSnapshot } from "./helpers/time"; +import { signDataVerifyTransfer, hashedData } from "./helpers/signData"; +import { pk } from "./helpers/testprivateKey"; +import { encodeProxyCall, encodeModuleCall } from "./helpers/encodeCall"; +import { catchRevert } from "./helpers/exceptions"; +import { setUpPolymathNetwork, deployGPMAndVerifyed, deployDummySTOAndVerifyed, deploySignedTMAndVerifyed} from "./helpers/createInstances"; + +const DummySTO = artifacts.require("./DummySTO.sol"); +const SecurityToken = artifacts.require("./SecurityToken.sol"); +const GeneralTransferManager = artifacts.require("./GeneralTransferManager"); +const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager"); +const SignedTransferManager = artifacts.require("./SignedTransferManager"); + +const Web3 = require("web3"); +const BigNumber = require("bignumber.js"); +const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port + +contract("SignedTransferManager", accounts => { + // Accounts Variable declaration + let account_polymath; + let account_issuer; + let token_owner; + let token_owner_pk; + let account_investor1; + let account_investor2; + let account_investor3; + let account_investor4; + + // investor Details + let fromTime = latestTime(); + let toTime = latestTime(); + let expiryTime = toTime + duration.days(15); + + let message = "Transaction Should Fail!"; + + // Contract Instance Declaration + let I_GeneralPermissionManagerFactory; + let I_GeneralTransferManagerFactory; + let I_SecurityTokenRegistryProxy; + let I_GeneralPermissionManager; + let I_GeneralTransferManager; + let I_ModuleRegistryProxy; + let I_ModuleRegistry; + let I_FeatureRegistry; + let I_SecurityTokenRegistry; + let I_DummySTOFactory; + let I_STFactory; + let I_SecurityToken; + let I_STRProxied; + let I_MRProxied; + let I_DummySTO; + let I_PolyToken; + let I_PolymathRegistry; + let I_SignedTransferManagerFactory; + let P_SignedTransferManagerFactory; + let I_SignedTransferManager; + + // SecurityToken Details + const name = "Team"; + const symbol = "sap"; + const tokenDetails = "This is equity type of issuance"; + const decimals = 18; + const contact = "team@polymath.network"; + + // Module key + const delegateManagerKey = 1; + const transferManagerKey = 2; + const stoKey = 3; + + // Initial fee for ticker registry and security token registry + const initRegFee = web3.utils.toWei("250"); + + // Dummy STO details + const startTime = latestTime() + duration.seconds(5000); // Start time will be 5000 seconds more than the latest time + const endTime = startTime + duration.days(80); // Add 80 days more + const cap = web3.utils.toWei("10", "ether"); + const someString = "A string which is not used"; + const STOParameters = ["uint256", "uint256", "uint256", "string"]; + + before(async () => { + // Accounts setup + account_polymath = accounts[0]; + account_issuer = accounts[1]; + + token_owner = account_issuer; + token_owner_pk = pk.account_1; + + account_investor1 = accounts[8]; + account_investor2 = accounts[9]; + account_investor3 = accounts[6]; + account_investor4 = accounts[7]; + + // Step 1: Deploy the genral PM ecosystem + let instances = await setUpPolymathNetwork(account_polymath, token_owner); + + [ + I_PolymathRegistry, + I_PolyToken, + I_FeatureRegistry, + I_ModuleRegistry, + I_ModuleRegistryProxy, + I_MRProxied, + I_GeneralTransferManagerFactory, + I_STFactory, + I_SecurityTokenRegistry, + I_SecurityTokenRegistryProxy, + I_STRProxied + ] = instances; + + // STEP 2: Deploy the GeneralPermissionManagerFactory + [I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + // STEP 3: Deploy the SignedTransferManagerFactory + [I_SignedTransferManagerFactory] = await deploySignedTMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, 0); + // STEP 4: Deploy the Paid SignedTransferManagerFactory + [P_SignedTransferManagerFactory] = await deploySignedTMAndVerifyed(account_polymath, I_MRProxied, I_PolyToken.address, web3.utils.toWei("500", "ether")); + + // Printing all the contract addresses + console.log(` + --------------------- Polymath Network Smart Contracts: --------------------- + PolymathRegistry: ${I_PolymathRegistry.address} + SecurityTokenRegistryProxy: ${I_SecurityTokenRegistryProxy.address} + SecurityTokenRegistry: ${I_SecurityTokenRegistry.address} + ModuleRegistryProxy: ${I_ModuleRegistryProxy.address} + ModuleRegistry: ${I_ModuleRegistry.address} + FeatureRegistry: ${I_FeatureRegistry.address} + + ManualApprovalTransferManagerFactory: ${I_SignedTransferManagerFactory.address} + + + ----------------------------------------------------------------------------- + `); + }); + + describe("Generate the SecurityToken", async () => { + it("Should register the ticker before the generation of the security token", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let tx = await I_STRProxied.registerTicker(token_owner, symbol, contact, { from: token_owner }); + assert.equal(tx.logs[0].args._owner, token_owner); + assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase()); + }); + + it("Should generate the new security token with the same symbol as registered above", async () => { + await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner }); + let _blockNo = latestBlock(); + let tx = await I_STRProxied.generateSecurityToken(name, symbol, tokenDetails, false, { from: token_owner }); + + // Verify the successful generation of the security token + assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed"); + + I_SecurityToken = SecurityToken.at(tx.logs[1].args._securityTokenAddress); + + const log = await promisifyLogWatch(I_SecurityToken.ModuleAdded({ from: _blockNo }), 1); + + // Verify that GeneralTransferManager module get added successfully or not + assert.equal(log.args._types[0].toNumber(), 2); + assert.equal(web3.utils.toUtf8(log.args._name), "GeneralTransferManager"); + }); + + it("Should intialize the auto attached modules", async () => { + let moduleData = (await I_SecurityToken.getModulesByType(2))[0]; + I_GeneralTransferManager = GeneralTransferManager.at(moduleData); + }); + }); + + + describe("signed transfer manager tests", async () => { + + it("Should Buy the tokens", async () => { + // Add the Investor in to the whitelist + + let tx = await I_GeneralTransferManager.modifyWhitelist( + account_investor1, + latestTime(), + latestTime(), + latestTime() + duration.days(10), + true, + { + from: account_issuer, + gas: 6000000 + } + ); + + assert.equal( + tx.logs[0].args._investor.toLowerCase(), + account_investor1.toLowerCase(), + "Failed in adding the investor in whitelist" + ); + + // Jump time + await increaseTime(5000); + + // Mint some tokens + await I_SecurityToken.mint(account_investor1, web3.utils.toWei("4", "ether"), { from: token_owner }); + + assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toNumber(), web3.utils.toWei("4", "ether")); + }); + + it("Should successfully attach the SignedTransferManager with the security token", async () => { + const tx = await I_SecurityToken.addModule(I_SignedTransferManagerFactory.address, "", 0, 0, { from: token_owner }); + assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "SignedTransferManager doesn't get deployed"); + assert.equal( + web3.utils.toUtf8(tx.logs[2].args._name), + "SignedTransferManager", + "SignedTransferManager module was not added" + ); + I_SignedTransferManager = SignedTransferManager.at(tx.logs[2].args._module); + }); + + it("should fail to transfer because transaction is not verified yet.", async () => { + await catchRevert(I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), { from: account_investor1 })); + }); + + it("should successfully add multiple signers to signersList", async () => { + await I_SignedTransferManager.updateSigners([account_investor3, account_investor4], [true, true], {from: token_owner}); + + assert.equal(await I_SignedTransferManager.signers(account_investor3), true); + assert.equal(await I_SignedTransferManager.signers(account_investor4), true); + }); + + it("should fail to change signers stats without permission", async () => { + await catchRevert(I_SignedTransferManager.updateSigners([account_investor3], [false], {from: account_investor2})); + }); + + // it("should not be able to invalid siganture if not in the signer list", async () => { + // //create a sig + // const sig = signDataVerifyTransfer( + // I_SignedTransferManager.address, + // account_investor1, + // account_investor2, + // web3.utils.toWei("1", "ether"), + // account_investor1 + // ); + + // console.log("signature is "+sig); + + // await catchRevert(I_SignedTransferManager.invalidSignature(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, {from: account_investor1})); + // }); + + // it("should not be able to invalid siganture if not the original signer while in the signer list", async () => { + // //create a sig + // const sig = signDataVerifyTransfer( + // I_SignedTransferManager.address, + // account_investor1, + // account_investor2, + // web3.utils.toWei("1", "ether"), + // account_investor4 + // ); + + // console.log("signature is "+sig); + + // await catchRevert(I_SignedTransferManager.invalidSignature(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, {from: account_investor3})); + // }); + + it("should be able to invalid siganture if sender is the signer and is in the signer list", async () => { + //create a sig + console.log("1"); + + const sig = signDataVerifyTransfer( + I_SignedTransferManager.address, + account_investor1, + account_investor2, + web3.utils.toWei("1", "ether"), + account_investor4 + ); + console.log("2"); + console.log("sig is"+sig); + + const hash = hashedData(I_SignedTransferManager.address, account_investor1, account_investor2, web3.utils.toWei("1", "ether")); + + console.log("hashed data is " + hash); + + // await I_SignedTransferManager.invalidSignature(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, {from: account_investor4}); + console.log("signer is "+ account_investor4); + // assert.equal(await I_SignedTransferManager.checkSignatureIsInvalid(sig, {from: account_investor4})); + console.log("recovered address is "+await I_SignedTransferManager.invalidSignature(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, hash, {from: account_investor4})); + }); + + // it("should allow transfer with valid sig", async () => { + // const sig = signDataVerifyTransfer( + // I_SignedTransferManager.address, + // account_investor1, + // account_investor2, + // web3.utils.toWei("1", "ether"), + // account_investor4 + // ); + + + // }); + + it("should not allow transfer if the sig is not valid", async () => { + + }); + }); +}); + + + + + + + + + + + + From 35f7134012447d7c0961006f77fcc321e7134810 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Tue, 16 Oct 2018 18:21:58 +0200 Subject: [PATCH 03/15] ready with double prefix --- .../TransferManager/SignedTransferManager.sol | 55 ++++++--- test/helpers/signData.js | 19 +--- test/y_signed_transfer_manager.js | 105 ++++++++++-------- 3 files changed, 95 insertions(+), 84 deletions(-) diff --git a/contracts/modules/TransferManager/SignedTransferManager.sol b/contracts/modules/TransferManager/SignedTransferManager.sol index 6a4ea9563..49e9c8d16 100644 --- a/contracts/modules/TransferManager/SignedTransferManager.sol +++ b/contracts/modules/TransferManager/SignedTransferManager.sol @@ -20,7 +20,8 @@ contract SignedTransferManager is ITransferManager { // Emit when signer stats was changed event UpdateSigners(address[] _signers, bool[] _signersStats); - // Emit when there is change in the flag variable called allowAllTransfers + + // Emit when a signature has been deemed invalid event InvalidSignature(bytes _data); @@ -42,10 +43,19 @@ contract SignedTransferManager is ITransferManager { return bytes4(0); } + /** + * @notice function to check if a signature is still valid + * @param _data signature + */ function checkSignatureIsInvalid(bytes _data) public view returns(bool){ return invalidSignatures[_data]; } + /** + * @notice function to remove or add signer(s) onto the signer mapping + * @param _signers address array of signers + * @param _signersStats bool array of signers stats + */ function updateSigners(address[] _signers, bool[] _signersStats) public withPerm(ADMIN) { require(_signers.length == _signersStats.length, "input array length does not match"); for(uint8 i=0; i<_signers.length; i++){ @@ -55,20 +65,22 @@ contract SignedTransferManager is ITransferManager { } /** - * @notice default implementation of verifyTransfer used by SecurityToken - * If the transfer request comes from the STO, it only checks that the investor is in the whitelist - * If the transfer request comes from a token holder, it checks that: - * a) Both are on the whitelist - * b) Seller's sale lockup period is over - * c) Buyer's purchase lockup is over + * @notice allow verify transfer with signature + * @param _from address transfer from + * @param _to address transfer to + * @param _amount transfer amount + * @param _data signature + * @param _isTransfer bool value of isTransfer + * Sig needs to be valid (not used or deemed as invalid) + * Signer needs to be in the signers mapping */ function verifyTransfer(address _from, address _to, uint256 _amount, bytes _data , bool _isTransfer) public returns(Result) { if (!paused) { require(invalidSignatures[_data] != true, "Invalid signature - signature is either used or deemed as invalid"); - bytes32 hash = keccak256(abi.encodePacked(this, _from, _to, _amount)); - address signer = _recoverSignerAdd(hash, _data); + bytes32 _hash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); + address signer = _recoverSignerAdd(_hash, _data); require(signers[signer] == true, "Invalid signature - signer is not on the list"); if(_isTransfer == true){ @@ -80,22 +92,31 @@ contract SignedTransferManager is ITransferManager { return Result.NA; } - function invalidSignature(address _from, address _to, uint256 _amount, bytes _data, bytes32 _hash) public view returns(address) { + /** + * @notice allow signers to deem a signature invalid + * @param _from address transfer from + * @param _to address transfer to + * @param _amount transfer amount + * @param _data signature + * Sig needs to be valid (not used or deemed as invalid) + * Signer needs to be in the signers mapping + */ + function invalidSignature(address _from, address _to, uint256 _amount, bytes _data) public { require(signers[msg.sender] == true, "Only signer is allowed to invalid signature."); require(invalidSignatures[_data] != true, "This signature is invalid."); - // bytes32 _hash = keccak256(abi.encodePacked(this, _from, _to, _amount)); + bytes32 hash = keccak256(abi.encodePacked(this, _from, _to, _amount)); + bytes32 _hash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); - address signer = _recoverSignerAdd(_hash,_data); - return signer; - // require(signer == msg.sender, "Incorrect Signer for this signature"); + // return signer; + require(_recoverSignerAdd(_hash,_data) == msg.sender, "Incorrect Signer for this signature"); - // invalidSignatures[_data] = true; - // emit InvalidSignature(_data); + invalidSignatures[_data] = true; + emit InvalidSignature(_data); } /** - * @notice used to verify the signature + * @notice used to recover signers' add from signature */ function _recoverSignerAdd(bytes32 _hash, bytes _data) internal view returns(address) { diff --git a/test/helpers/signData.js b/test/helpers/signData.js index bed34d91f..9ad064896 100644 --- a/test/helpers/signData.js +++ b/test/helpers/signData.js @@ -29,25 +29,8 @@ function signDataVerifyTransfer (tmAddress, fromAddress, toAddress, amount, acco packedData = web3.sha3(`0x${packedData.toString("hex")}`, { encoding: "hex" }); return web3.eth.sign(account, packedData); - -} - -// test only for hashing -function hashedData (tmAddress, fromAddress, toAddress, amount) { - let packedData = utils - .solidityKeccak256( - ["address", "address", "address", "uint256"], - [tmAddress, fromAddress, toAddress, amount] - ) - .slice(2); - packedData = new Buffer(packedData, "hex"); - packedData = Buffer.concat([new Buffer(`\x19Ethereum Signed Message:\n${packedData.length.toString()}`), packedData]); - packedData = web3.sha3(`0x${packedData.toString("hex")}`, { encoding: "hex" }); - - return packedData; - } module.exports = { - signData, signDataVerifyTransfer, hashedData + signData, signDataVerifyTransfer }; diff --git a/test/y_signed_transfer_manager.js b/test/y_signed_transfer_manager.js index 00e49e880..e8fea8689 100644 --- a/test/y_signed_transfer_manager.js +++ b/test/y_signed_transfer_manager.js @@ -1,7 +1,7 @@ import latestTime from "./helpers/latestTime"; import { duration, promisifyLogWatch, latestBlock } from "./helpers/utils"; import takeSnapshot, { increaseTime, revertToSnapshot } from "./helpers/time"; -import { signDataVerifyTransfer, hashedData } from "./helpers/signData"; +import { signDataVerifyTransfer } from "./helpers/signData"; import { pk } from "./helpers/testprivateKey"; import { encodeProxyCall, encodeModuleCall } from "./helpers/encodeCall"; import { catchRevert } from "./helpers/exceptions"; @@ -223,40 +223,33 @@ contract("SignedTransferManager", accounts => { await catchRevert(I_SignedTransferManager.updateSigners([account_investor3], [false], {from: account_investor2})); }); - // it("should not be able to invalid siganture if not in the signer list", async () => { - // //create a sig - // const sig = signDataVerifyTransfer( - // I_SignedTransferManager.address, - // account_investor1, - // account_investor2, - // web3.utils.toWei("1", "ether"), - // account_investor1 - // ); + it("should not be able to invalid siganture if not in the signer list", async () => { - // console.log("signature is "+sig); + const sig = signDataVerifyTransfer( + I_SignedTransferManager.address, + account_investor1, + account_investor2, + web3.utils.toWei("1", "ether"), + account_investor1 + ); - // await catchRevert(I_SignedTransferManager.invalidSignature(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, {from: account_investor1})); - // }); + await catchRevert(I_SignedTransferManager.invalidSignature(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, {from: account_investor1})); + }); - // it("should not be able to invalid siganture if not the original signer while in the signer list", async () => { - // //create a sig - // const sig = signDataVerifyTransfer( - // I_SignedTransferManager.address, - // account_investor1, - // account_investor2, - // web3.utils.toWei("1", "ether"), - // account_investor4 - // ); + it("should not be able to invalid siganture if not the original signer even if it's in the signer list", async () => { - // console.log("signature is "+sig); + const sig = signDataVerifyTransfer( + I_SignedTransferManager.address, + account_investor1, + account_investor2, + web3.utils.toWei("1", "ether"), + account_investor4 + ); - // await catchRevert(I_SignedTransferManager.invalidSignature(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, {from: account_investor3})); - // }); + await catchRevert(I_SignedTransferManager.invalidSignature(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, {from: account_investor3})); + }); it("should be able to invalid siganture if sender is the signer and is in the signer list", async () => { - //create a sig - console.log("1"); - const sig = signDataVerifyTransfer( I_SignedTransferManager.address, account_investor1, @@ -264,34 +257,48 @@ contract("SignedTransferManager", accounts => { web3.utils.toWei("1", "ether"), account_investor4 ); - console.log("2"); - console.log("sig is"+sig); - - const hash = hashedData(I_SignedTransferManager.address, account_investor1, account_investor2, web3.utils.toWei("1", "ether")); - console.log("hashed data is " + hash); - - // await I_SignedTransferManager.invalidSignature(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, {from: account_investor4}); - console.log("signer is "+ account_investor4); - // assert.equal(await I_SignedTransferManager.checkSignatureIsInvalid(sig, {from: account_investor4})); - console.log("recovered address is "+await I_SignedTransferManager.invalidSignature(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, hash, {from: account_investor4})); + await I_SignedTransferManager.invalidSignature(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, {from: account_investor4}); + assert.equal(await I_SignedTransferManager.checkSignatureIsInvalid(sig), true); }); - // it("should allow transfer with valid sig", async () => { - // const sig = signDataVerifyTransfer( - // I_SignedTransferManager.address, - // account_investor1, - // account_investor2, - // web3.utils.toWei("1", "ether"), - // account_investor4 - // ); + it("should not allow transfer if the sig is already used", async () => { + const sig = signDataVerifyTransfer( + I_SignedTransferManager.address, + account_investor1, + account_investor2, + web3.utils.toWei("1", "ether"), + account_investor4 + ); + await catchRevert(I_SignedTransferManager.verifyTransfer(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, true, {from: account_investor4})); + }); - // }); + it("should allow transfer with valid sig", async () => { + const sig = signDataVerifyTransfer( + I_SignedTransferManager.address, + account_investor1, + account_investor2, + web3.utils.toWei("1", "ether"), + account_investor3 + ); + + await I_SignedTransferManager.verifyTransfer(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, true, {from: account_investor3}); + assert.equal(await I_SignedTransferManager.checkSignatureIsInvalid(sig), true); + }); - it("should not allow transfer if the sig is not valid", async () => { - + it("should not allow transfer if the signer is not on the signer list", async () => { + const sig = signDataVerifyTransfer( + I_SignedTransferManager.address, + account_investor1, + account_investor2, + web3.utils.toWei("1", "ether"), + account_investor2 + ); + await catchRevert(I_SignedTransferManager.verifyTransfer(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, true, {from: account_investor2})); + }); + }); }); From bb36e8519be950f28a57c35fcdfdcc152549c539 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Thu, 18 Oct 2018 17:20:13 +0200 Subject: [PATCH 04/15] change to ethers.js sign api --- .../TransferManager/SignedTransferManager.sol | 25 +++++++-- test/helpers/signData.js | 19 ++++++- test/y_signed_transfer_manager.js | 55 +++++++++++-------- 3 files changed, 69 insertions(+), 30 deletions(-) diff --git a/contracts/modules/TransferManager/SignedTransferManager.sol b/contracts/modules/TransferManager/SignedTransferManager.sol index 49e9c8d16..523ee60ce 100644 --- a/contracts/modules/TransferManager/SignedTransferManager.sol +++ b/contracts/modules/TransferManager/SignedTransferManager.sol @@ -101,18 +101,33 @@ contract SignedTransferManager is ITransferManager { * Sig needs to be valid (not used or deemed as invalid) * Signer needs to be in the signers mapping */ - function invalidSignature(address _from, address _to, uint256 _amount, bytes _data) public { + // function invalidSignature(address _from, address _to, uint256 _amount, bytes _data) public { + // require(signers[msg.sender] == true, "Only signer is allowed to invalid signature."); + // require(invalidSignatures[_data] != true, "This signature is invalid."); + + // bytes32 hash = keccak256(abi.encodePacked(this, _from, _to, _amount)); + // bytes32 _hash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); + + // // return signer; + // require(_recoverSignerAdd(_hash,_data) == msg.sender, "Incorrect Signer for this signature"); + + // invalidSignatures[_data] = true; + // emit InvalidSignature(_data); + // } + + function invalidSignature(address _from, address _to, uint256 _amount, bytes _data) public view returns(address) { require(signers[msg.sender] == true, "Only signer is allowed to invalid signature."); require(invalidSignatures[_data] != true, "This signature is invalid."); bytes32 hash = keccak256(abi.encodePacked(this, _from, _to, _amount)); bytes32 _hash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); - // return signer; - require(_recoverSignerAdd(_hash,_data) == msg.sender, "Incorrect Signer for this signature"); + return _recoverSignerAdd(hash,_data); + // require(_recoverSignerAdd(_hash,_data) == msg.sender, "Incorrect Signer for this signature"); + + // invalidSignatures[_data] = true; + // emit InvalidSignature(_data); - invalidSignatures[_data] = true; - emit InvalidSignature(_data); } /** diff --git a/test/helpers/signData.js b/test/helpers/signData.js index 9ad064896..6c3eee496 100644 --- a/test/helpers/signData.js +++ b/test/helpers/signData.js @@ -17,7 +17,7 @@ function signData (tmAddress, investorAddress, fromTime, toTime, expiryTime, res } // sign data for verify tranfer function -function signDataVerifyTransfer (tmAddress, fromAddress, toAddress, amount, account) { +function signDataVerifyTransfer2 (tmAddress, fromAddress, toAddress, amount, account) { let packedData = utils .solidityKeccak256( ["address", "address", "address", "uint256"], @@ -31,6 +31,23 @@ function signDataVerifyTransfer (tmAddress, fromAddress, toAddress, amount, acco return web3.eth.sign(account, packedData); } +// test +function signDataVerifyTransfer (tmAddress, fromAddress, toAddress, amount, pk) { + let packedData = utils + .solidityKeccak256( + ["address", "address", "address", "uint256"], + [tmAddress, fromAddress, toAddress, amount] + ) + .slice(2); + packedData = new Buffer(packedData, "hex"); + packedData = Buffer.concat([new Buffer(`\x19Ethereum Signed Message:\n${packedData.length.toString()}`), packedData]); + packedData = web3.sha3(`0x${packedData.toString("hex")}`, { encoding: "hex" }); + + let wallet = new ethers.Wallet(pk.indexOf('0x') === 0 ? pk : '0x' + pk); + + return wallet.signMessage(packedData); +} + module.exports = { signData, signDataVerifyTransfer }; diff --git a/test/y_signed_transfer_manager.js b/test/y_signed_transfer_manager.js index e8fea8689..c1e7de26a 100644 --- a/test/y_signed_transfer_manager.js +++ b/test/y_signed_transfer_manager.js @@ -213,41 +213,45 @@ contract("SignedTransferManager", accounts => { }); it("should successfully add multiple signers to signersList", async () => { - await I_SignedTransferManager.updateSigners([account_investor3, account_investor4], [true, true], {from: token_owner}); + await I_SignedTransferManager.updateSigners([account_investor3, account_investor4, token_owner], [true, true, true], {from: token_owner}); assert.equal(await I_SignedTransferManager.signers(account_investor3), true); assert.equal(await I_SignedTransferManager.signers(account_investor4), true); + assert.equal(await I_SignedTransferManager.signers(token_owner), true); }); it("should fail to change signers stats without permission", async () => { await catchRevert(I_SignedTransferManager.updateSigners([account_investor3], [false], {from: account_investor2})); }); - it("should not be able to invalid siganture if not in the signer list", async () => { + // it("should not be able to invalid siganture if not in the signer list", async () => { - const sig = signDataVerifyTransfer( - I_SignedTransferManager.address, - account_investor1, - account_investor2, - web3.utils.toWei("1", "ether"), - account_investor1 - ); + // console.log("pk is "+token_owner_pk); - await catchRevert(I_SignedTransferManager.invalidSignature(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, {from: account_investor1})); - }); + // const sig = signDataVerifyTransfer( + // I_SignedTransferManager.address, + // account_investor1, + // account_investor2, + // web3.utils.toWei("1", "ether"), + // //account_investor1 + // token_owner_pk + // ); - it("should not be able to invalid siganture if not the original signer even if it's in the signer list", async () => { + // await catchRevert(I_SignedTransferManager.invalidSignature(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, {from: account_investor1})); + // }); - const sig = signDataVerifyTransfer( - I_SignedTransferManager.address, - account_investor1, - account_investor2, - web3.utils.toWei("1", "ether"), - account_investor4 - ); + // it("should not be able to invalid siganture if not the original signer even if it's in the signer list", async () => { - await catchRevert(I_SignedTransferManager.invalidSignature(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, {from: account_investor3})); - }); + // const sig = signDataVerifyTransfer( + // I_SignedTransferManager.address, + // account_investor1, + // account_investor2, + // web3.utils.toWei("1", "ether"), + // account_investor4 + // ); + + // await catchRevert(I_SignedTransferManager.invalidSignature(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, {from: account_investor3})); + // }); it("should be able to invalid siganture if sender is the signer and is in the signer list", async () => { const sig = signDataVerifyTransfer( @@ -255,11 +259,14 @@ contract("SignedTransferManager", accounts => { account_investor1, account_investor2, web3.utils.toWei("1", "ether"), - account_investor4 + // account_investor4 + token_owner_pk ); - await I_SignedTransferManager.invalidSignature(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, {from: account_investor4}); - assert.equal(await I_SignedTransferManager.checkSignatureIsInvalid(sig), true); + console.log("token owner is "+ token_owner); + + console.log(await I_SignedTransferManager.invalidSignature(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, {from: token_owner})); + // assert.equal(await I_SignedTransferManager.checkSignatureIsInvalid(sig), true); }); it("should not allow transfer if the sig is already used", async () => { From 845ba871d9128e673c229df64dd377bd49babb3d Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Tue, 13 Nov 2018 07:43:26 -0500 Subject: [PATCH 05/15] rick fixed sign data --- .../TransferManager/SignedTransferManager.sol | 34 +++++++++---------- test/helpers/signData.js | 4 +-- test/y_signed_transfer_manager.js | 15 ++++---- 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/contracts/modules/TransferManager/SignedTransferManager.sol b/contracts/modules/TransferManager/SignedTransferManager.sol index 523ee60ce..b41beb626 100644 --- a/contracts/modules/TransferManager/SignedTransferManager.sol +++ b/contracts/modules/TransferManager/SignedTransferManager.sol @@ -101,35 +101,35 @@ contract SignedTransferManager is ITransferManager { * Sig needs to be valid (not used or deemed as invalid) * Signer needs to be in the signers mapping */ - // function invalidSignature(address _from, address _to, uint256 _amount, bytes _data) public { + function invalidSignature(address _from, address _to, uint256 _amount, bytes _data) public { + require(signers[msg.sender] == true, "Only signer is allowed to invalid signature."); + require(invalidSignatures[_data] != true, "This signature is invalid."); + + bytes32 hash = keccak256(abi.encodePacked(this, _from, _to, _amount)); + bytes32 _hash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); + + // return signer; + require(_recoverSignerAdd(_hash,_data) == msg.sender, "Incorrect Signer for this signature"); + + invalidSignatures[_data] = true; + emit InvalidSignature(_data); + } + + // function invalidSignature(address _from, address _to, uint256 _amount, bytes _data) public view returns(address) { // require(signers[msg.sender] == true, "Only signer is allowed to invalid signature."); // require(invalidSignatures[_data] != true, "This signature is invalid."); + // // we have to double hash due to our web3 default hash once // bytes32 hash = keccak256(abi.encodePacked(this, _from, _to, _amount)); // bytes32 _hash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); - // // return signer; + // // return _recoverSignerAdd(_hash,_data); // require(_recoverSignerAdd(_hash,_data) == msg.sender, "Incorrect Signer for this signature"); // invalidSignatures[_data] = true; // emit InvalidSignature(_data); // } - function invalidSignature(address _from, address _to, uint256 _amount, bytes _data) public view returns(address) { - require(signers[msg.sender] == true, "Only signer is allowed to invalid signature."); - require(invalidSignatures[_data] != true, "This signature is invalid."); - - bytes32 hash = keccak256(abi.encodePacked(this, _from, _to, _amount)); - bytes32 _hash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); - - return _recoverSignerAdd(hash,_data); - // require(_recoverSignerAdd(_hash,_data) == msg.sender, "Incorrect Signer for this signature"); - - // invalidSignatures[_data] = true; - // emit InvalidSignature(_data); - - } - /** * @notice used to recover signers' add from signature */ diff --git a/test/helpers/signData.js b/test/helpers/signData.js index 6c3eee496..a750ae573 100644 --- a/test/helpers/signData.js +++ b/test/helpers/signData.js @@ -17,7 +17,7 @@ function signData (tmAddress, investorAddress, fromTime, toTime, expiryTime, res } // sign data for verify tranfer function -function signDataVerifyTransfer2 (tmAddress, fromAddress, toAddress, amount, account) { +function signDataVerifyTransfer (tmAddress, fromAddress, toAddress, amount, account) { let packedData = utils .solidityKeccak256( ["address", "address", "address", "uint256"], @@ -32,7 +32,7 @@ function signDataVerifyTransfer2 (tmAddress, fromAddress, toAddress, amount, acc } // test -function signDataVerifyTransfer (tmAddress, fromAddress, toAddress, amount, pk) { +function signDataVerifyTransfer2 (tmAddress, fromAddress, toAddress, amount, pk) { let packedData = utils .solidityKeccak256( ["address", "address", "address", "uint256"], diff --git a/test/y_signed_transfer_manager.js b/test/y_signed_transfer_manager.js index c1e7de26a..03cc80edf 100644 --- a/test/y_signed_transfer_manager.js +++ b/test/y_signed_transfer_manager.js @@ -259,14 +259,15 @@ contract("SignedTransferManager", accounts => { account_investor1, account_investor2, web3.utils.toWei("1", "ether"), - // account_investor4 - token_owner_pk + token_owner + // token_owner_pk ); console.log("token owner is "+ token_owner); - console.log(await I_SignedTransferManager.invalidSignature(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, {from: token_owner})); - // assert.equal(await I_SignedTransferManager.checkSignatureIsInvalid(sig), true); + await I_SignedTransferManager.invalidSignature(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, {from: token_owner}); + console.log("2"); + assert.equal(await I_SignedTransferManager.checkSignatureIsInvalid(sig), true); }); it("should not allow transfer if the sig is already used", async () => { @@ -275,10 +276,10 @@ contract("SignedTransferManager", accounts => { account_investor1, account_investor2, web3.utils.toWei("1", "ether"), - account_investor4 + token_owner ); - - await catchRevert(I_SignedTransferManager.verifyTransfer(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, true, {from: account_investor4})); + // I_SignedTransferManager.verifyTransfer(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, true, {from: token_owner}); + await catchRevert(I_SignedTransferManager.verifyTransfer(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, true, {from: token_owner})); }); it("should allow transfer with valid sig", async () => { From ebcd869b03761750b68fb2b9262f3a57111e2a27 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Thu, 15 Nov 2018 08:45:16 -0500 Subject: [PATCH 06/15] fix all the requested changes and tested ok --- .../TransferManager/SignedTransferManager.sol | 35 +++++++------------ test/y_signed_transfer_manager.js | 2 +- 2 files changed, 13 insertions(+), 24 deletions(-) diff --git a/contracts/modules/TransferManager/SignedTransferManager.sol b/contracts/modules/TransferManager/SignedTransferManager.sol index b41beb626..b70c34466 100644 --- a/contracts/modules/TransferManager/SignedTransferManager.sol +++ b/contracts/modules/TransferManager/SignedTransferManager.sol @@ -76,18 +76,22 @@ contract SignedTransferManager is ITransferManager { */ function verifyTransfer(address _from, address _to, uint256 _amount, bytes _data , bool _isTransfer) public returns(Result) { if (!paused) { + + require(_isTransfer == false || msg.sender == securityToken, "Sender is not the owner"); require(invalidSignatures[_data] != true, "Invalid signature - signature is either used or deemed as invalid"); bytes32 hash = keccak256(abi.encodePacked(this, _from, _to, _amount)); - bytes32 _hash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); - address signer = _recoverSignerAdd(_hash, _data); + bytes32 prependedHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); + address signer = _recoverSignerAdd(prependedHash, _data); + require(signers[signer] == true, "Invalid signature - signer is not on the list"); - if(_isTransfer == true){ - invalidSignatures[_data] = true; + if (signers[signer] != true){ + return Result.NA; + } else { + invalidSignatures[_data] = true; + return Result.VALID; } - - return Result.VALID; } return Result.NA; } @@ -106,30 +110,15 @@ contract SignedTransferManager is ITransferManager { require(invalidSignatures[_data] != true, "This signature is invalid."); bytes32 hash = keccak256(abi.encodePacked(this, _from, _to, _amount)); - bytes32 _hash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); + bytes32 prependedHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); // return signer; - require(_recoverSignerAdd(_hash,_data) == msg.sender, "Incorrect Signer for this signature"); + require(_recoverSignerAdd(prependedHash,_data) == msg.sender, "Incorrect Signer for this signature"); invalidSignatures[_data] = true; emit InvalidSignature(_data); } - // function invalidSignature(address _from, address _to, uint256 _amount, bytes _data) public view returns(address) { - // require(signers[msg.sender] == true, "Only signer is allowed to invalid signature."); - // require(invalidSignatures[_data] != true, "This signature is invalid."); - - // // we have to double hash due to our web3 default hash once - // bytes32 hash = keccak256(abi.encodePacked(this, _from, _to, _amount)); - // bytes32 _hash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); - - // // return _recoverSignerAdd(_hash,_data); - // require(_recoverSignerAdd(_hash,_data) == msg.sender, "Incorrect Signer for this signature"); - - // invalidSignatures[_data] = true; - // emit InvalidSignature(_data); - // } - /** * @notice used to recover signers' add from signature */ diff --git a/test/y_signed_transfer_manager.js b/test/y_signed_transfer_manager.js index 03cc80edf..89955b8fe 100644 --- a/test/y_signed_transfer_manager.js +++ b/test/y_signed_transfer_manager.js @@ -291,7 +291,7 @@ contract("SignedTransferManager", accounts => { account_investor3 ); - await I_SignedTransferManager.verifyTransfer(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, true, {from: account_investor3}); + await I_SignedTransferManager.verifyTransfer(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, false, {from: account_investor3}); assert.equal(await I_SignedTransferManager.checkSignatureIsInvalid(sig), true); }); From 07f1b8f3fa3ea4f6df87ee8dee12e377820ef3f2 Mon Sep 17 00:00:00 2001 From: Ricko Date: Fri, 16 Nov 2018 08:18:00 -0500 Subject: [PATCH 07/15] updated logic in verify transfer function as requested by Adam D. --- .../modules/TransferManager/SignedTransferManager.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/modules/TransferManager/SignedTransferManager.sol b/contracts/modules/TransferManager/SignedTransferManager.sol index b70c34466..6d049d64c 100644 --- a/contracts/modules/TransferManager/SignedTransferManager.sol +++ b/contracts/modules/TransferManager/SignedTransferManager.sol @@ -83,14 +83,14 @@ contract SignedTransferManager is ITransferManager { bytes32 hash = keccak256(abi.encodePacked(this, _from, _to, _amount)); bytes32 prependedHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); address signer = _recoverSignerAdd(prependedHash, _data); - - require(signers[signer] == true, "Invalid signature - signer is not on the list"); - + if (signers[signer] != true){ return Result.NA; - } else { + } else if(_isTransfer == true) { invalidSignatures[_data] = true; return Result.VALID; + } else { + return Result.VALID; } } return Result.NA; From 2abea319e42ec67e3d37a18d9415c43f857e01ee Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Fri, 16 Nov 2018 08:18:45 -0500 Subject: [PATCH 08/15] Apply suggestions from code review gas saver Co-Authored-By: comeonbuddy --- contracts/modules/TransferManager/SignedTransferManager.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/modules/TransferManager/SignedTransferManager.sol b/contracts/modules/TransferManager/SignedTransferManager.sol index 6d049d64c..425f9c950 100644 --- a/contracts/modules/TransferManager/SignedTransferManager.sol +++ b/contracts/modules/TransferManager/SignedTransferManager.sol @@ -58,7 +58,7 @@ contract SignedTransferManager is ITransferManager { */ function updateSigners(address[] _signers, bool[] _signersStats) public withPerm(ADMIN) { require(_signers.length == _signersStats.length, "input array length does not match"); - for(uint8 i=0; i<_signers.length; i++){ + for(uint256 i=0; i<_signers.length; i++){ signers[_signers[i]] = _signersStats[i]; } emit UpdateSigners(_signers, _signersStats); From 95c4b84eec4f1202cd4533a177c946c9386ef0a3 Mon Sep 17 00:00:00 2001 From: Ricko Date: Fri, 16 Nov 2018 08:24:21 -0500 Subject: [PATCH 09/15] added data length check data input length can not be 0 --- contracts/modules/TransferManager/SignedTransferManager.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/modules/TransferManager/SignedTransferManager.sol b/contracts/modules/TransferManager/SignedTransferManager.sol index 425f9c950..d25ae7ca8 100644 --- a/contracts/modules/TransferManager/SignedTransferManager.sol +++ b/contracts/modules/TransferManager/SignedTransferManager.sol @@ -78,6 +78,7 @@ contract SignedTransferManager is ITransferManager { if (!paused) { require(_isTransfer == false || msg.sender == securityToken, "Sender is not the owner"); + require(_data.length != 0, "Invalid data input"); require(invalidSignatures[_data] != true, "Invalid signature - signature is either used or deemed as invalid"); bytes32 hash = keccak256(abi.encodePacked(this, _from, _to, _amount)); From 3ad887bfb336ad75f676ba931b0d7039835cbf2c Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Tue, 20 Nov 2018 10:34:36 +0100 Subject: [PATCH 10/15] WIP saving changes, fixed issues with signed function --- .../TransferManager/SignedTransferManager.sol | 16 ++++-- test/helpers/signData.js | 17 ------ test/y_signed_transfer_manager.js | 54 ++++--------------- 3 files changed, 23 insertions(+), 64 deletions(-) diff --git a/contracts/modules/TransferManager/SignedTransferManager.sol b/contracts/modules/TransferManager/SignedTransferManager.sol index b70c34466..725700f72 100644 --- a/contracts/modules/TransferManager/SignedTransferManager.sol +++ b/contracts/modules/TransferManager/SignedTransferManager.sol @@ -77,14 +77,24 @@ contract SignedTransferManager is ITransferManager { function verifyTransfer(address _from, address _to, uint256 _amount, bytes _data , bool _isTransfer) public returns(Result) { if (!paused) { - require(_isTransfer == false || msg.sender == securityToken, "Sender is not the owner"); + // not using require to avoid revert in this function + + if (_isTransfer != false || msg.sender != securityToken){ + return Result.INVALID; //Sender is not the owner + } + + if(_data.length == 0){ + return Result.INVALID; // data input check + } require(invalidSignatures[_data] != true, "Invalid signature - signature is either used or deemed as invalid"); bytes32 hash = keccak256(abi.encodePacked(this, _from, _to, _amount)); bytes32 prependedHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); address signer = _recoverSignerAdd(prependedHash, _data); - - require(signers[signer] == true, "Invalid signature - signer is not on the list"); + + if (signers[signer] == false) { + return Result.INVALID; //Invalid signature - signer is not on the list + } if (signers[signer] != true){ return Result.NA; diff --git a/test/helpers/signData.js b/test/helpers/signData.js index 530eca9e8..549ebdf4f 100644 --- a/test/helpers/signData.js +++ b/test/helpers/signData.js @@ -32,23 +32,6 @@ function signDataVerifyTransfer (tmAddress, fromAddress, toAddress, amount, acco return web3.eth.sign(account, packedData); } -// test -function signDataVerifyTransfer2 (tmAddress, fromAddress, toAddress, amount, pk) { - let packedData = utils - .solidityKeccak256( - ["address", "address", "address", "uint256"], - [tmAddress, fromAddress, toAddress, amount] - ) - .slice(2); - packedData = new Buffer(packedData, "hex"); - packedData = Buffer.concat([new Buffer(`\x19Ethereum Signed Message:\n${packedData.length.toString()}`), packedData]); - packedData = web3.sha3(`0x${packedData.toString("hex")}`, { encoding: "hex" }); - - let wallet = new ethers.Wallet(pk.indexOf('0x') === 0 ? pk : '0x' + pk); - - return wallet.signMessage(packedData); -} - module.exports = { signData, signDataVerifyTransfer }; diff --git a/test/y_signed_transfer_manager.js b/test/y_signed_transfer_manager.js index 89955b8fe..ba2eb2f2f 100644 --- a/test/y_signed_transfer_manager.js +++ b/test/y_signed_transfer_manager.js @@ -224,34 +224,6 @@ contract("SignedTransferManager", accounts => { await catchRevert(I_SignedTransferManager.updateSigners([account_investor3], [false], {from: account_investor2})); }); - // it("should not be able to invalid siganture if not in the signer list", async () => { - - // console.log("pk is "+token_owner_pk); - - // const sig = signDataVerifyTransfer( - // I_SignedTransferManager.address, - // account_investor1, - // account_investor2, - // web3.utils.toWei("1", "ether"), - // //account_investor1 - // token_owner_pk - // ); - - // await catchRevert(I_SignedTransferManager.invalidSignature(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, {from: account_investor1})); - // }); - - // it("should not be able to invalid siganture if not the original signer even if it's in the signer list", async () => { - - // const sig = signDataVerifyTransfer( - // I_SignedTransferManager.address, - // account_investor1, - // account_investor2, - // web3.utils.toWei("1", "ether"), - // account_investor4 - // ); - - // await catchRevert(I_SignedTransferManager.invalidSignature(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, {from: account_investor3})); - // }); it("should be able to invalid siganture if sender is the signer and is in the signer list", async () => { const sig = signDataVerifyTransfer( @@ -260,7 +232,6 @@ contract("SignedTransferManager", accounts => { account_investor2, web3.utils.toWei("1", "ether"), token_owner - // token_owner_pk ); console.log("token owner is "+ token_owner); @@ -278,8 +249,10 @@ contract("SignedTransferManager", accounts => { web3.utils.toWei("1", "ether"), token_owner ); - // I_SignedTransferManager.verifyTransfer(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, true, {from: token_owner}); - await catchRevert(I_SignedTransferManager.verifyTransfer(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, true, {from: token_owner})); + + let tx = await I_SignedTransferManager.verifyTransfer.call(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, true, {from: token_owner}); + + assert.equal(tx.toNumber(), 0); }); it("should allow transfer with valid sig", async () => { @@ -291,7 +264,9 @@ contract("SignedTransferManager", accounts => { account_investor3 ); - await I_SignedTransferManager.verifyTransfer(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, false, {from: account_investor3}); + let tx = await I_SignedTransferManager.verifyTransfer(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, true, {from: token_owner}); + // console.log(tx.logs[0]); + console.log(tx.receipts); assert.equal(await I_SignedTransferManager.checkSignatureIsInvalid(sig), true); }); @@ -303,21 +278,12 @@ contract("SignedTransferManager", accounts => { web3.utils.toWei("1", "ether"), account_investor2 ); - await catchRevert(I_SignedTransferManager.verifyTransfer(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, true, {from: account_investor2})); + + let tx = await I_SignedTransferManager.verifyTransfer.call(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, true, {from: token_owner}); + console.log("output is "+tx.toNumber()); }); }); }); - - - - - - - - - - - From a14644ae2dc923ed63f8580145c76a082db2df47 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Wed, 21 Nov 2018 10:57:54 +0100 Subject: [PATCH 11/15] fixing test cases calling from STO --- .../TransferManager/SignedTransferManager.sol | 6 ++--- test/y_signed_transfer_manager.js | 26 +++++++++++-------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/contracts/modules/TransferManager/SignedTransferManager.sol b/contracts/modules/TransferManager/SignedTransferManager.sol index 725700f72..275bcf237 100644 --- a/contracts/modules/TransferManager/SignedTransferManager.sol +++ b/contracts/modules/TransferManager/SignedTransferManager.sol @@ -77,11 +77,9 @@ contract SignedTransferManager is ITransferManager { function verifyTransfer(address _from, address _to, uint256 _amount, bytes _data , bool _isTransfer) public returns(Result) { if (!paused) { - // not using require to avoid revert in this function + require (_isTransfer == false || msg.sender == securityToken, "Sender is not the owner"); - if (_isTransfer != false || msg.sender != securityToken){ - return Result.INVALID; //Sender is not the owner - } + // not using require to avoid revert in this function if(_data.length == 0){ return Result.INVALID; // data input check diff --git a/test/y_signed_transfer_manager.js b/test/y_signed_transfer_manager.js index ba2eb2f2f..5cef39c4b 100644 --- a/test/y_signed_transfer_manager.js +++ b/test/y_signed_transfer_manager.js @@ -237,7 +237,6 @@ contract("SignedTransferManager", accounts => { console.log("token owner is "+ token_owner); await I_SignedTransferManager.invalidSignature(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, {from: token_owner}); - console.log("2"); assert.equal(await I_SignedTransferManager.checkSignatureIsInvalid(sig), true); }); @@ -250,23 +249,28 @@ contract("SignedTransferManager", accounts => { token_owner ); - let tx = await I_SignedTransferManager.verifyTransfer.call(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, true, {from: token_owner}); + console.log("2"); - assert.equal(tx.toNumber(), 0); + await catchRevert (I_SignedTransferManager.verifyTransfer(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, false, {from: token_owner})); }); it("should allow transfer with valid sig", async () => { + + console.log("owner is a signer status is " + await I_SignedTransferManager.signers(token_owner, {from: token_owner})); + const sig = signDataVerifyTransfer( I_SignedTransferManager.address, - account_investor1, + token_owner, account_investor2, - web3.utils.toWei("1", "ether"), - account_investor3 + web3.utils.toWei("0.5", "ether"), + token_owner ); - - let tx = await I_SignedTransferManager.verifyTransfer(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, true, {from: token_owner}); - // console.log(tx.logs[0]); - console.log(tx.receipts); + + // let tx = await I_SignedTransferManager.verifyTransfer(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, false, {from: token_owner}); + console.log("owner balance is" + await web3.eth.getBalance(token_owner)); + // test call security token transfer function + let tx = await I_SecurityToken.transferWithData(account_investor2, web3.utils.toWei("0.5", "ether"), sig, {from: token_owner}); + console.log("3"); assert.equal(await I_SignedTransferManager.checkSignatureIsInvalid(sig), true); }); @@ -279,7 +283,7 @@ contract("SignedTransferManager", accounts => { account_investor2 ); - let tx = await I_SignedTransferManager.verifyTransfer.call(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, true, {from: token_owner}); + let tx = await I_SignedTransferManager.verifyTransfer.call(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, false, {from: token_owner}); console.log("output is "+tx.toNumber()); }); From fb3e6ba568a7b8239247a8cf612cf1b2a2d597a4 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Wed, 21 Nov 2018 12:20:18 +0100 Subject: [PATCH 12/15] WIP - bugs calling ST --- test/y_signed_transfer_manager.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/y_signed_transfer_manager.js b/test/y_signed_transfer_manager.js index 5cef39c4b..e2255e482 100644 --- a/test/y_signed_transfer_manager.js +++ b/test/y_signed_transfer_manager.js @@ -260,16 +260,18 @@ contract("SignedTransferManager", accounts => { const sig = signDataVerifyTransfer( I_SignedTransferManager.address, - token_owner, + account_investor1, account_investor2, - web3.utils.toWei("0.5", "ether"), + web3.utils.toWei("0.05", "ether"), token_owner ); // let tx = await I_SignedTransferManager.verifyTransfer(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, false, {from: token_owner}); - console.log("owner balance is" + await web3.eth.getBalance(token_owner)); + console.log("owner token balance is " + (await I_SecurityToken.balanceOf(account_investor1)).toNumber()); + console.log("is this sig invalid?"+ await I_SignedTransferManager.checkSignatureIsInvalid(sig)); + // test call security token transfer function - let tx = await I_SecurityToken.transferWithData(account_investor2, web3.utils.toWei("0.5", "ether"), sig, {from: token_owner}); + let tx = await I_SecurityToken.transferWithData(account_investor2, web3.utils.toWei("0.05", "ether"), sig, {from: account_investor1}); console.log("3"); assert.equal(await I_SignedTransferManager.checkSignatureIsInvalid(sig), true); }); From 1138ad6f2fe62a391c5f4cbeb99fdc08a63fd2e4 Mon Sep 17 00:00:00 2001 From: comeonbuddy Date: Wed, 21 Nov 2018 18:45:30 +0100 Subject: [PATCH 13/15] WIP ST test --- test/y_signed_transfer_manager.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/y_signed_transfer_manager.js b/test/y_signed_transfer_manager.js index e2255e482..729ada4d2 100644 --- a/test/y_signed_transfer_manager.js +++ b/test/y_signed_transfer_manager.js @@ -262,7 +262,7 @@ contract("SignedTransferManager", accounts => { I_SignedTransferManager.address, account_investor1, account_investor2, - web3.utils.toWei("0.05", "ether"), + web3.utils.toWei("1", "ether"), token_owner ); @@ -271,7 +271,7 @@ contract("SignedTransferManager", accounts => { console.log("is this sig invalid?"+ await I_SignedTransferManager.checkSignatureIsInvalid(sig)); // test call security token transfer function - let tx = await I_SecurityToken.transferWithData(account_investor2, web3.utils.toWei("0.05", "ether"), sig, {from: account_investor1}); + let tx = await I_SecurityToken.transferWithData(account_investor2, web3.utils.toWei("1", "ether"), sig, {from: account_investor1}); console.log("3"); assert.equal(await I_SignedTransferManager.checkSignatureIsInvalid(sig), true); }); From 1c1db2e561e0aa2d9a2bb3eb2b41e578ea675479 Mon Sep 17 00:00:00 2001 From: Mudit Gupta Date: Thu, 22 Nov 2018 09:59:49 +0530 Subject: [PATCH 14/15] Fixed test case --- test/y_signed_transfer_manager.js | 32 +++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/test/y_signed_transfer_manager.js b/test/y_signed_transfer_manager.js index 729ada4d2..1f5ffc122 100644 --- a/test/y_signed_transfer_manager.js +++ b/test/y_signed_transfer_manager.js @@ -230,30 +230,16 @@ contract("SignedTransferManager", accounts => { I_SignedTransferManager.address, account_investor1, account_investor2, - web3.utils.toWei("1", "ether"), + web3.utils.toWei("2", "ether"), token_owner ); console.log("token owner is "+ token_owner); - await I_SignedTransferManager.invalidSignature(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, {from: token_owner}); + await I_SignedTransferManager.invalidSignature(account_investor1, account_investor2, web3.utils.toWei("2", "ether"), sig, {from: token_owner}); assert.equal(await I_SignedTransferManager.checkSignatureIsInvalid(sig), true); }); - it("should not allow transfer if the sig is already used", async () => { - const sig = signDataVerifyTransfer( - I_SignedTransferManager.address, - account_investor1, - account_investor2, - web3.utils.toWei("1", "ether"), - token_owner - ); - - console.log("2"); - - await catchRevert (I_SignedTransferManager.verifyTransfer(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, false, {from: token_owner})); - }); - it("should allow transfer with valid sig", async () => { console.log("owner is a signer status is " + await I_SignedTransferManager.signers(token_owner, {from: token_owner})); @@ -276,6 +262,20 @@ contract("SignedTransferManager", accounts => { assert.equal(await I_SignedTransferManager.checkSignatureIsInvalid(sig), true); }); + it("should not allow transfer if the sig is already used", async () => { + const sig = signDataVerifyTransfer( + I_SignedTransferManager.address, + account_investor1, + account_investor2, + web3.utils.toWei("1", "ether"), + token_owner + ); + + console.log("2"); + + await catchRevert (I_SignedTransferManager.verifyTransfer(account_investor1, account_investor2, web3.utils.toWei("1", "ether"), sig, false, {from: token_owner})); + }); + it("should not allow transfer if the signer is not on the signer list", async () => { const sig = signDataVerifyTransfer( I_SignedTransferManager.address, From 26ab8eda2a87398c067bf2ec3a6abf4398bad450 Mon Sep 17 00:00:00 2001 From: Adam Dossa Date: Mon, 26 Nov 2018 22:00:44 +0000 Subject: [PATCH 15/15] Move to Experimental folder --- .../TransferManager/SignedTransferManager.sol | 12 ++++++------ .../TransferManager/SignedTransferManagerFactory.sol | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) rename contracts/modules/{ => Experimental}/TransferManager/SignedTransferManager.sol (97%) rename contracts/modules/{ => Experimental}/TransferManager/SignedTransferManagerFactory.sol (99%) diff --git a/contracts/modules/TransferManager/SignedTransferManager.sol b/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol similarity index 97% rename from contracts/modules/TransferManager/SignedTransferManager.sol rename to contracts/modules/Experimental/TransferManager/SignedTransferManager.sol index 66225be38..12699f74f 100644 --- a/contracts/modules/TransferManager/SignedTransferManager.sol +++ b/contracts/modules/Experimental/TransferManager/SignedTransferManager.sol @@ -1,6 +1,6 @@ pragma solidity ^0.4.24; -import "./ITransferManager.sol"; +import "../../TransferManager/ITransferManager.sol"; import "openzeppelin-solidity/contracts/math/SafeMath.sol"; /** @@ -59,7 +59,7 @@ contract SignedTransferManager is ITransferManager { function updateSigners(address[] _signers, bool[] _signersStats) public withPerm(ADMIN) { require(_signers.length == _signersStats.length, "input array length does not match"); for(uint256 i=0; i<_signers.length; i++){ - signers[_signers[i]] = _signersStats[i]; + signers[_signers[i]] = _signersStats[i]; } emit UpdateSigners(_signers, _signersStats); } @@ -84,7 +84,7 @@ contract SignedTransferManager is ITransferManager { if(_data.length == 0){ return Result.INVALID; // data input check } - + require(invalidSignatures[_data] != true, "Invalid signature - signature is either used or deemed as invalid"); bytes32 hash = keccak256(abi.encodePacked(this, _from, _to, _amount)); bytes32 prependedHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash)); @@ -128,8 +128,8 @@ contract SignedTransferManager is ITransferManager { /** * @notice used to recover signers' add from signature */ - function _recoverSignerAdd(bytes32 _hash, bytes _data) internal view returns(address) { - + function _recoverSignerAdd(bytes32 _hash, bytes _data) internal pure returns(address) { + //Check that the signature is valid require(_data.length == 65, "Date input length is invalid"); @@ -152,7 +152,7 @@ contract SignedTransferManager is ITransferManager { return ecrecover(keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _hash)), v, r, s); } - + /** * @notice Return the permissions flag that are associated with ManualApproval transfer manager */ diff --git a/contracts/modules/TransferManager/SignedTransferManagerFactory.sol b/contracts/modules/Experimental/TransferManager/SignedTransferManagerFactory.sol similarity index 99% rename from contracts/modules/TransferManager/SignedTransferManagerFactory.sol rename to contracts/modules/Experimental/TransferManager/SignedTransferManagerFactory.sol index da2bfd4b4..af26dfcb2 100644 --- a/contracts/modules/TransferManager/SignedTransferManagerFactory.sol +++ b/contracts/modules/Experimental/TransferManager/SignedTransferManagerFactory.sol @@ -1,7 +1,7 @@ pragma solidity ^0.4.24; import "./SignedTransferManager.sol"; -import "../ModuleFactory.sol"; +import "../../ModuleFactory.sol"; /** * @title Factory for deploying SignedTransferManager module