add token contracts for testing purposes and refactor TokenMovements utils

This commit is contained in:
mmv 2019-05-31 17:58:35 +04:00
parent bfa5a52bc4
commit 6902bad091
33 changed files with 52063 additions and 1850 deletions

View File

@ -0,0 +1,148 @@
{
"contractName": "DevDependenciesGetter",
"abi": [],
"metadata": "{\"compiler\":{\"version\":\"0.5.8+commit.23d335f2\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"methods\":{}},\"userdoc\":{\"methods\":{}}},\"settings\":{\"compilationTarget\":{\"/home/mmv/work/safe-react/contracts/DevDependencies.sol\":\"DevDependenciesGetter\"},\"evmVersion\":\"petersburg\",\"libraries\":{},\"optimizer\":{\"enabled\":true,\"runs\":500},\"remappings\":[]},\"sources\":{\"/home/mmv/work/safe-react/contracts/DevDependencies.sol\":{\"keccak256\":\"0xc649617f3c51e58509bdd0910726bd84a52f232b6aaf5790ac72f6e84ccb1b58\",\"urls\":[\"bzzr://57b15b2fd6a6a15523665a1f369e8b395a5649504f807114fedff42cf1b430b3\"]},\"/home/mmv/work/safe-react/src/test/contracts/TokenOMG.sol\":{\"keccak256\":\"0x099d05859e51af8b24539b47e0d181a17409d51063263f8a8d53280818c69d4d\",\"urls\":[\"bzzr://4eb926d078f8111367c3a180e7eb99f36528b95c871e1004c626f1cb5487f5dc\"]},\"/home/mmv/work/safe-react/src/test/contracts/TokenRDN.sol\":{\"keccak256\":\"0xbd1fc040f6b4f7b68bb7e6b745d02c571d7baf992c5a3a34d57392f624d7043c\",\"urls\":[\"bzzr://fdd020e4fe5f62e961acccce8733276ad3aca6dbe7ccff3f860476774cf6bdab\"]},\"@gnosis.pm/util-contracts/contracts/GnosisStandardToken.sol\":{\"keccak256\":\"0xdec5028208406e811c449a04e2932f7efeae629388cb6124550b8b048a645556\",\"urls\":[\"bzzr://f3d13a708f543b3ce72745cab321e6daf25d935fd12ba55a4152f1113eb6d5e4\"]},\"@gnosis.pm/util-contracts/contracts/Math.sol\":{\"keccak256\":\"0x857768cd0d460e33778dcde29e997b539640bbf37ea23832213b2e5039147ea5\",\"urls\":[\"bzzr://628f7e63a0d6a092aad389b70cc55d6d9c10cd9753f3644d5ea9dc75a3314a8e\"]},\"@gnosis.pm/util-contracts/contracts/Proxy.sol\":{\"keccak256\":\"0x2ff8795110cceafcab1010f157a4dd33e46378bb88fbdc3c313a6f0d62e3444f\",\"urls\":[\"bzzr://66d77feaf648ca17dd620f3e27463b4b6e6031fec7ccd64dfffc4c30bd57b467\"]},\"@gnosis.pm/util-contracts/contracts/Token.sol\":{\"keccak256\":\"0x364778f634c900ed83553e17ef1284bd33fa68a738e668f664b4a0fa675bb586\",\"urls\":[\"bzzr://cb31caaf3364dbf5d688adb10de074284845b142c26d23a47b09ee510dd4a432\"]}},\"version\":1}",
"bytecode": "0x6080604052348015600f57600080fd5b50603580601d6000396000f3fe6080604052600080fdfea165627a7a723058205e4f8760788b4c49e4643557d735f7312e842b538cebaa480b66c5e3577d34cb0029",
"deployedBytecode": "0x6080604052600080fdfea165627a7a723058205e4f8760788b4c49e4643557d735f7312e842b538cebaa480b66c5e3577d34cb0029",
"sourceMap": "116:33:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;116:33:0;;;;;;;",
"deployedSourceMap": "116:33:0:-;;;;;",
"source": "pragma solidity ^0.5.2;\n\nimport \"../src/test/contracts/TokenOMG.sol\";\nimport \"../src/test/contracts/TokenRDN.sol\";\n\ncontract DevDependenciesGetter {}",
"sourcePath": "/home/mmv/work/safe-react/contracts/DevDependencies.sol",
"ast": {
"absolutePath": "/home/mmv/work/safe-react/contracts/DevDependencies.sol",
"exportedSymbols": {
"DevDependenciesGetter": [
4
]
},
"id": 5,
"nodeType": "SourceUnit",
"nodes": [
{
"id": 1,
"literals": [
"solidity",
"^",
"0.5",
".2"
],
"nodeType": "PragmaDirective",
"src": "0:23:0"
},
{
"absolutePath": "/home/mmv/work/safe-react/src/test/contracts/TokenOMG.sol",
"file": "../src/test/contracts/TokenOMG.sol",
"id": 2,
"nodeType": "ImportDirective",
"scope": 5,
"sourceUnit": 90,
"src": "25:44:0",
"symbolAliases": [],
"unitAlias": ""
},
{
"absolutePath": "/home/mmv/work/safe-react/src/test/contracts/TokenRDN.sol",
"file": "../src/test/contracts/TokenRDN.sol",
"id": 3,
"nodeType": "ImportDirective",
"scope": 5,
"sourceUnit": 118,
"src": "70:44:0",
"symbolAliases": [],
"unitAlias": ""
},
{
"baseContracts": [],
"contractDependencies": [],
"contractKind": "contract",
"documentation": null,
"fullyImplemented": true,
"id": 4,
"linearizedBaseContracts": [
4
],
"name": "DevDependenciesGetter",
"nodeType": "ContractDefinition",
"nodes": [],
"scope": 5,
"src": "116:33:0"
}
],
"src": "0:149:0"
},
"legacyAST": {
"absolutePath": "/home/mmv/work/safe-react/contracts/DevDependencies.sol",
"exportedSymbols": {
"DevDependenciesGetter": [
4
]
},
"id": 5,
"nodeType": "SourceUnit",
"nodes": [
{
"id": 1,
"literals": [
"solidity",
"^",
"0.5",
".2"
],
"nodeType": "PragmaDirective",
"src": "0:23:0"
},
{
"absolutePath": "/home/mmv/work/safe-react/src/test/contracts/TokenOMG.sol",
"file": "../src/test/contracts/TokenOMG.sol",
"id": 2,
"nodeType": "ImportDirective",
"scope": 5,
"sourceUnit": 90,
"src": "25:44:0",
"symbolAliases": [],
"unitAlias": ""
},
{
"absolutePath": "/home/mmv/work/safe-react/src/test/contracts/TokenRDN.sol",
"file": "../src/test/contracts/TokenRDN.sol",
"id": 3,
"nodeType": "ImportDirective",
"scope": 5,
"sourceUnit": 118,
"src": "70:44:0",
"symbolAliases": [],
"unitAlias": ""
},
{
"baseContracts": [],
"contractDependencies": [],
"contractKind": "contract",
"documentation": null,
"fullyImplemented": true,
"id": 4,
"linearizedBaseContracts": [
4
],
"name": "DevDependenciesGetter",
"nodeType": "ContractDefinition",
"nodes": [],
"scope": 5,
"src": "116:33:0"
}
],
"src": "0:149:0"
},
"compiler": {
"name": "solc",
"version": "0.5.8+commit.23d335f2.Emscripten.clang"
},
"networks": {},
"schemaVersion": "3.0.10",
"updatedAt": "2019-05-31T13:47:05.338Z",
"devdoc": {
"methods": {}
},
"userdoc": {
"methods": {}
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,983 @@
{
"contractName": "Proxied",
"abi": [
{
"constant": true,
"inputs": [],
"name": "masterCopy",
"outputs": [
{
"name": "",
"type": "address"
}
],
"payable": false,
"stateMutability": "view",
"type": "function"
}
],
"metadata": "{\"compiler\":{\"version\":\"0.5.8+commit.23d335f2\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"constant\":true,\"inputs\":[],\"name\":\"masterCopy\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Alan Lu - <alan@gnosis.pm>\",\"methods\":{},\"title\":\"Proxied - indicates that a contract will be proxied. Also defines storage requirements for Proxy.\"},\"userdoc\":{\"methods\":{}}},\"settings\":{\"compilationTarget\":{\"@gnosis.pm/util-contracts/contracts/Proxy.sol\":\"Proxied\"},\"evmVersion\":\"petersburg\",\"libraries\":{},\"optimizer\":{\"enabled\":true,\"runs\":500},\"remappings\":[]},\"sources\":{\"@gnosis.pm/util-contracts/contracts/Proxy.sol\":{\"keccak256\":\"0x2ff8795110cceafcab1010f157a4dd33e46378bb88fbdc3c313a6f0d62e3444f\",\"urls\":[\"bzzr://66d77feaf648ca17dd620f3e27463b4b6e6031fec7ccd64dfffc4c30bd57b467\"]}},\"version\":1}",
"bytecode": "0x6080604052348015600f57600080fd5b5060a48061001e6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063a619486e14602d575b600080fd5b6033605c565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b60005473ffffffffffffffffffffffffffffffffffffffff168156fea165627a7a7230582030927156db8f845fed095b245b70d15291cf8c9a8cdd88be16cdf598edc721190029",
"deployedBytecode": "0x6080604052348015600f57600080fd5b506004361060285760003560e01c8063a619486e14602d575b600080fd5b6033605c565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b60005473ffffffffffffffffffffffffffffffffffffffff168156fea165627a7a7230582030927156db8f845fed095b245b70d15291cf8c9a8cdd88be16cdf598edc721190029",
"sourceMap": "173:51:6:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;173:51:6;;;;;;;",
"deployedSourceMap": "173:51:6:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;173:51:6;;;;;;;;;;;;;;;;;;;196:25;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;:::o",
"source": "pragma solidity ^0.5.2;\n\n/// @title Proxied - indicates that a contract will be proxied. Also defines storage requirements for Proxy.\n/// @author Alan Lu - <alan@gnosis.pm>\ncontract Proxied {\n address public masterCopy;\n}\n\n/// @title Proxy - Generic proxy contract allows to execute all transactions applying the code of a master contract.\n/// @author Stefan George - <stefan@gnosis.pm>\ncontract Proxy is Proxied {\n /// @dev Constructor function sets address of master copy contract.\n /// @param _masterCopy Master copy address.\n constructor(address _masterCopy) public {\n require(_masterCopy != address(0), \"The master copy is required\");\n masterCopy = _masterCopy;\n }\n\n /// @dev Fallback function forwards all transactions and returns all received return data.\n function() external payable {\n address _masterCopy = masterCopy;\n assembly {\n calldatacopy(0, 0, calldatasize)\n let success := delegatecall(not(0), _masterCopy, 0, calldatasize, 0, 0)\n returndatacopy(0, 0, returndatasize)\n switch success\n case 0 {\n revert(0, returndatasize)\n }\n default {\n return(0, returndatasize)\n }\n }\n }\n}\n",
"sourcePath": "@gnosis.pm/util-contracts/contracts/Proxy.sol",
"ast": {
"absolutePath": "@gnosis.pm/util-contracts/contracts/Proxy.sol",
"exportedSymbols": {
"Proxied": [
1463
],
"Proxy": [
1494
]
},
"id": 1495,
"nodeType": "SourceUnit",
"nodes": [
{
"id": 1460,
"literals": [
"solidity",
"^",
"0.5",
".2"
],
"nodeType": "PragmaDirective",
"src": "0:23:6"
},
{
"baseContracts": [],
"contractDependencies": [],
"contractKind": "contract",
"documentation": "@title Proxied - indicates that a contract will be proxied. Also defines storage requirements for Proxy.\n @author Alan Lu - <alan@gnosis.pm>",
"fullyImplemented": true,
"id": 1463,
"linearizedBaseContracts": [
1463
],
"name": "Proxied",
"nodeType": "ContractDefinition",
"nodes": [
{
"constant": false,
"id": 1462,
"name": "masterCopy",
"nodeType": "VariableDeclaration",
"scope": 1463,
"src": "196:25:6",
"stateVariable": true,
"storageLocation": "default",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
},
"typeName": {
"id": 1461,
"name": "address",
"nodeType": "ElementaryTypeName",
"src": "196:7:6",
"stateMutability": "nonpayable",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
}
},
"value": null,
"visibility": "public"
}
],
"scope": 1495,
"src": "173:51:6"
},
{
"baseContracts": [
{
"arguments": null,
"baseName": {
"contractScope": null,
"id": 1464,
"name": "Proxied",
"nodeType": "UserDefinedTypeName",
"referencedDeclaration": 1463,
"src": "408:7:6",
"typeDescriptions": {
"typeIdentifier": "t_contract$_Proxied_$1463",
"typeString": "contract Proxied"
}
},
"id": 1465,
"nodeType": "InheritanceSpecifier",
"src": "408:7:6"
}
],
"contractDependencies": [
1463
],
"contractKind": "contract",
"documentation": "@title Proxy - Generic proxy contract allows to execute all transactions applying the code of a master contract.\n @author Stefan George - <stefan@gnosis.pm>",
"fullyImplemented": true,
"id": 1494,
"linearizedBaseContracts": [
1494,
1463
],
"name": "Proxy",
"nodeType": "ContractDefinition",
"nodes": [
{
"body": {
"id": 1483,
"nodeType": "Block",
"src": "582:116:6",
"statements": [
{
"expression": {
"argumentTypes": null,
"arguments": [
{
"argumentTypes": null,
"commonType": {
"typeIdentifier": "t_address",
"typeString": "address"
},
"id": 1475,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftExpression": {
"argumentTypes": null,
"id": 1471,
"name": "_masterCopy",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 1467,
"src": "600:11:6",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
}
},
"nodeType": "BinaryOperation",
"operator": "!=",
"rightExpression": {
"argumentTypes": null,
"arguments": [
{
"argumentTypes": null,
"hexValue": "30",
"id": 1473,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "623:1:6",
"subdenomination": null,
"typeDescriptions": {
"typeIdentifier": "t_rational_0_by_1",
"typeString": "int_const 0"
},
"value": "0"
}
],
"expression": {
"argumentTypes": [
{
"typeIdentifier": "t_rational_0_by_1",
"typeString": "int_const 0"
}
],
"id": 1472,
"isConstant": false,
"isLValue": false,
"isPure": true,
"lValueRequested": false,
"nodeType": "ElementaryTypeNameExpression",
"src": "615:7:6",
"typeDescriptions": {
"typeIdentifier": "t_type$_t_address_$",
"typeString": "type(address)"
},
"typeName": "address"
},
"id": 1474,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "typeConversion",
"lValueRequested": false,
"names": [],
"nodeType": "FunctionCall",
"src": "615:10:6",
"typeDescriptions": {
"typeIdentifier": "t_address_payable",
"typeString": "address payable"
}
},
"src": "600:25:6",
"typeDescriptions": {
"typeIdentifier": "t_bool",
"typeString": "bool"
}
},
{
"argumentTypes": null,
"hexValue": "546865206d617374657220636f7079206973207265717569726564",
"id": 1476,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "string",
"lValueRequested": false,
"nodeType": "Literal",
"src": "627:29:6",
"subdenomination": null,
"typeDescriptions": {
"typeIdentifier": "t_stringliteral_2e9921edd8141a51172691d5d51dd1cbeb601d8d4953527c9d36e0bffd20fed9",
"typeString": "literal_string \"The master copy is required\""
},
"value": "The master copy is required"
}
],
"expression": {
"argumentTypes": [
{
"typeIdentifier": "t_bool",
"typeString": "bool"
},
{
"typeIdentifier": "t_stringliteral_2e9921edd8141a51172691d5d51dd1cbeb601d8d4953527c9d36e0bffd20fed9",
"typeString": "literal_string \"The master copy is required\""
}
],
"id": 1470,
"name": "require",
"nodeType": "Identifier",
"overloadedDeclarations": [
1581,
1582
],
"referencedDeclaration": 1582,
"src": "592:7:6",
"typeDescriptions": {
"typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$",
"typeString": "function (bool,string memory) pure"
}
},
"id": 1477,
"isConstant": false,
"isLValue": false,
"isPure": false,
"kind": "functionCall",
"lValueRequested": false,
"names": [],
"nodeType": "FunctionCall",
"src": "592:65:6",
"typeDescriptions": {
"typeIdentifier": "t_tuple$__$",
"typeString": "tuple()"
}
},
"id": 1478,
"nodeType": "ExpressionStatement",
"src": "592:65:6"
},
{
"expression": {
"argumentTypes": null,
"id": 1481,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftHandSide": {
"argumentTypes": null,
"id": 1479,
"name": "masterCopy",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 1462,
"src": "667:10:6",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
}
},
"nodeType": "Assignment",
"operator": "=",
"rightHandSide": {
"argumentTypes": null,
"id": 1480,
"name": "_masterCopy",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 1467,
"src": "680:11:6",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
}
},
"src": "667:24:6",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
}
},
"id": 1482,
"nodeType": "ExpressionStatement",
"src": "667:24:6"
}
]
},
"documentation": "@dev Constructor function sets address of master copy contract.\n @param _masterCopy Master copy address.",
"id": 1484,
"implemented": true,
"kind": "constructor",
"modifiers": [],
"name": "",
"nodeType": "FunctionDefinition",
"parameters": {
"id": 1468,
"nodeType": "ParameterList",
"parameters": [
{
"constant": false,
"id": 1467,
"name": "_masterCopy",
"nodeType": "VariableDeclaration",
"scope": 1484,
"src": "554:19:6",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
},
"typeName": {
"id": 1466,
"name": "address",
"nodeType": "ElementaryTypeName",
"src": "554:7:6",
"stateMutability": "nonpayable",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
}
},
"value": null,
"visibility": "internal"
}
],
"src": "553:21:6"
},
"returnParameters": {
"id": 1469,
"nodeType": "ParameterList",
"parameters": [],
"src": "582:0:6"
},
"scope": 1494,
"src": "542:156:6",
"stateMutability": "nonpayable",
"superFunction": null,
"visibility": "public"
},
{
"body": {
"id": 1492,
"nodeType": "Block",
"src": "827:462:6",
"statements": [
{
"assignments": [
1488
],
"declarations": [
{
"constant": false,
"id": 1488,
"name": "_masterCopy",
"nodeType": "VariableDeclaration",
"scope": 1492,
"src": "837:19:6",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
},
"typeName": {
"id": 1487,
"name": "address",
"nodeType": "ElementaryTypeName",
"src": "837:7:6",
"stateMutability": "nonpayable",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
}
},
"value": null,
"visibility": "internal"
}
],
"id": 1490,
"initialValue": {
"argumentTypes": null,
"id": 1489,
"name": "masterCopy",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 1462,
"src": "859:10:6",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
}
},
"nodeType": "VariableDeclarationStatement",
"src": "837:32:6"
},
{
"externalReferences": [
{
"_masterCopy": {
"declaration": 1488,
"isOffset": false,
"isSlot": false,
"src": "983:11:6",
"valueSize": 1
}
}
],
"id": 1491,
"nodeType": "InlineAssembly",
"operations": "{\n calldatacopy(0, 0, calldatasize())\n let success := delegatecall(not(0), _masterCopy, 0, calldatasize(), 0, 0)\n returndatacopy(0, 0, returndatasize())\n switch success\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n}",
"src": "879:404:6"
}
]
},
"documentation": "@dev Fallback function forwards all transactions and returns all received return data.",
"id": 1493,
"implemented": true,
"kind": "fallback",
"modifiers": [],
"name": "",
"nodeType": "FunctionDefinition",
"parameters": {
"id": 1485,
"nodeType": "ParameterList",
"parameters": [],
"src": "807:2:6"
},
"returnParameters": {
"id": 1486,
"nodeType": "ParameterList",
"parameters": [],
"src": "827:0:6"
},
"scope": 1494,
"src": "799:490:6",
"stateMutability": "payable",
"superFunction": null,
"visibility": "external"
}
],
"scope": 1495,
"src": "390:901:6"
}
],
"src": "0:1292:6"
},
"legacyAST": {
"absolutePath": "@gnosis.pm/util-contracts/contracts/Proxy.sol",
"exportedSymbols": {
"Proxied": [
1463
],
"Proxy": [
1494
]
},
"id": 1495,
"nodeType": "SourceUnit",
"nodes": [
{
"id": 1460,
"literals": [
"solidity",
"^",
"0.5",
".2"
],
"nodeType": "PragmaDirective",
"src": "0:23:6"
},
{
"baseContracts": [],
"contractDependencies": [],
"contractKind": "contract",
"documentation": "@title Proxied - indicates that a contract will be proxied. Also defines storage requirements for Proxy.\n @author Alan Lu - <alan@gnosis.pm>",
"fullyImplemented": true,
"id": 1463,
"linearizedBaseContracts": [
1463
],
"name": "Proxied",
"nodeType": "ContractDefinition",
"nodes": [
{
"constant": false,
"id": 1462,
"name": "masterCopy",
"nodeType": "VariableDeclaration",
"scope": 1463,
"src": "196:25:6",
"stateVariable": true,
"storageLocation": "default",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
},
"typeName": {
"id": 1461,
"name": "address",
"nodeType": "ElementaryTypeName",
"src": "196:7:6",
"stateMutability": "nonpayable",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
}
},
"value": null,
"visibility": "public"
}
],
"scope": 1495,
"src": "173:51:6"
},
{
"baseContracts": [
{
"arguments": null,
"baseName": {
"contractScope": null,
"id": 1464,
"name": "Proxied",
"nodeType": "UserDefinedTypeName",
"referencedDeclaration": 1463,
"src": "408:7:6",
"typeDescriptions": {
"typeIdentifier": "t_contract$_Proxied_$1463",
"typeString": "contract Proxied"
}
},
"id": 1465,
"nodeType": "InheritanceSpecifier",
"src": "408:7:6"
}
],
"contractDependencies": [
1463
],
"contractKind": "contract",
"documentation": "@title Proxy - Generic proxy contract allows to execute all transactions applying the code of a master contract.\n @author Stefan George - <stefan@gnosis.pm>",
"fullyImplemented": true,
"id": 1494,
"linearizedBaseContracts": [
1494,
1463
],
"name": "Proxy",
"nodeType": "ContractDefinition",
"nodes": [
{
"body": {
"id": 1483,
"nodeType": "Block",
"src": "582:116:6",
"statements": [
{
"expression": {
"argumentTypes": null,
"arguments": [
{
"argumentTypes": null,
"commonType": {
"typeIdentifier": "t_address",
"typeString": "address"
},
"id": 1475,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftExpression": {
"argumentTypes": null,
"id": 1471,
"name": "_masterCopy",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 1467,
"src": "600:11:6",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
}
},
"nodeType": "BinaryOperation",
"operator": "!=",
"rightExpression": {
"argumentTypes": null,
"arguments": [
{
"argumentTypes": null,
"hexValue": "30",
"id": 1473,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "623:1:6",
"subdenomination": null,
"typeDescriptions": {
"typeIdentifier": "t_rational_0_by_1",
"typeString": "int_const 0"
},
"value": "0"
}
],
"expression": {
"argumentTypes": [
{
"typeIdentifier": "t_rational_0_by_1",
"typeString": "int_const 0"
}
],
"id": 1472,
"isConstant": false,
"isLValue": false,
"isPure": true,
"lValueRequested": false,
"nodeType": "ElementaryTypeNameExpression",
"src": "615:7:6",
"typeDescriptions": {
"typeIdentifier": "t_type$_t_address_$",
"typeString": "type(address)"
},
"typeName": "address"
},
"id": 1474,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "typeConversion",
"lValueRequested": false,
"names": [],
"nodeType": "FunctionCall",
"src": "615:10:6",
"typeDescriptions": {
"typeIdentifier": "t_address_payable",
"typeString": "address payable"
}
},
"src": "600:25:6",
"typeDescriptions": {
"typeIdentifier": "t_bool",
"typeString": "bool"
}
},
{
"argumentTypes": null,
"hexValue": "546865206d617374657220636f7079206973207265717569726564",
"id": 1476,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "string",
"lValueRequested": false,
"nodeType": "Literal",
"src": "627:29:6",
"subdenomination": null,
"typeDescriptions": {
"typeIdentifier": "t_stringliteral_2e9921edd8141a51172691d5d51dd1cbeb601d8d4953527c9d36e0bffd20fed9",
"typeString": "literal_string \"The master copy is required\""
},
"value": "The master copy is required"
}
],
"expression": {
"argumentTypes": [
{
"typeIdentifier": "t_bool",
"typeString": "bool"
},
{
"typeIdentifier": "t_stringliteral_2e9921edd8141a51172691d5d51dd1cbeb601d8d4953527c9d36e0bffd20fed9",
"typeString": "literal_string \"The master copy is required\""
}
],
"id": 1470,
"name": "require",
"nodeType": "Identifier",
"overloadedDeclarations": [
1581,
1582
],
"referencedDeclaration": 1582,
"src": "592:7:6",
"typeDescriptions": {
"typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$",
"typeString": "function (bool,string memory) pure"
}
},
"id": 1477,
"isConstant": false,
"isLValue": false,
"isPure": false,
"kind": "functionCall",
"lValueRequested": false,
"names": [],
"nodeType": "FunctionCall",
"src": "592:65:6",
"typeDescriptions": {
"typeIdentifier": "t_tuple$__$",
"typeString": "tuple()"
}
},
"id": 1478,
"nodeType": "ExpressionStatement",
"src": "592:65:6"
},
{
"expression": {
"argumentTypes": null,
"id": 1481,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftHandSide": {
"argumentTypes": null,
"id": 1479,
"name": "masterCopy",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 1462,
"src": "667:10:6",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
}
},
"nodeType": "Assignment",
"operator": "=",
"rightHandSide": {
"argumentTypes": null,
"id": 1480,
"name": "_masterCopy",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 1467,
"src": "680:11:6",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
}
},
"src": "667:24:6",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
}
},
"id": 1482,
"nodeType": "ExpressionStatement",
"src": "667:24:6"
}
]
},
"documentation": "@dev Constructor function sets address of master copy contract.\n @param _masterCopy Master copy address.",
"id": 1484,
"implemented": true,
"kind": "constructor",
"modifiers": [],
"name": "",
"nodeType": "FunctionDefinition",
"parameters": {
"id": 1468,
"nodeType": "ParameterList",
"parameters": [
{
"constant": false,
"id": 1467,
"name": "_masterCopy",
"nodeType": "VariableDeclaration",
"scope": 1484,
"src": "554:19:6",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
},
"typeName": {
"id": 1466,
"name": "address",
"nodeType": "ElementaryTypeName",
"src": "554:7:6",
"stateMutability": "nonpayable",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
}
},
"value": null,
"visibility": "internal"
}
],
"src": "553:21:6"
},
"returnParameters": {
"id": 1469,
"nodeType": "ParameterList",
"parameters": [],
"src": "582:0:6"
},
"scope": 1494,
"src": "542:156:6",
"stateMutability": "nonpayable",
"superFunction": null,
"visibility": "public"
},
{
"body": {
"id": 1492,
"nodeType": "Block",
"src": "827:462:6",
"statements": [
{
"assignments": [
1488
],
"declarations": [
{
"constant": false,
"id": 1488,
"name": "_masterCopy",
"nodeType": "VariableDeclaration",
"scope": 1492,
"src": "837:19:6",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
},
"typeName": {
"id": 1487,
"name": "address",
"nodeType": "ElementaryTypeName",
"src": "837:7:6",
"stateMutability": "nonpayable",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
}
},
"value": null,
"visibility": "internal"
}
],
"id": 1490,
"initialValue": {
"argumentTypes": null,
"id": 1489,
"name": "masterCopy",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 1462,
"src": "859:10:6",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
}
},
"nodeType": "VariableDeclarationStatement",
"src": "837:32:6"
},
{
"externalReferences": [
{
"_masterCopy": {
"declaration": 1488,
"isOffset": false,
"isSlot": false,
"src": "983:11:6",
"valueSize": 1
}
}
],
"id": 1491,
"nodeType": "InlineAssembly",
"operations": "{\n calldatacopy(0, 0, calldatasize())\n let success := delegatecall(not(0), _masterCopy, 0, calldatasize(), 0, 0)\n returndatacopy(0, 0, returndatasize())\n switch success\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n}",
"src": "879:404:6"
}
]
},
"documentation": "@dev Fallback function forwards all transactions and returns all received return data.",
"id": 1493,
"implemented": true,
"kind": "fallback",
"modifiers": [],
"name": "",
"nodeType": "FunctionDefinition",
"parameters": {
"id": 1485,
"nodeType": "ParameterList",
"parameters": [],
"src": "807:2:6"
},
"returnParameters": {
"id": 1486,
"nodeType": "ParameterList",
"parameters": [],
"src": "827:0:6"
},
"scope": 1494,
"src": "799:490:6",
"stateMutability": "payable",
"superFunction": null,
"visibility": "external"
}
],
"scope": 1495,
"src": "390:901:6"
}
],
"src": "0:1292:6"
},
"compiler": {
"name": "solc",
"version": "0.5.8+commit.23d335f2.Emscripten.clang"
},
"networks": {},
"schemaVersion": "3.0.10",
"updatedAt": "2019-05-31T13:47:05.362Z",
"devdoc": {
"author": "Alan Lu - <alan@gnosis.pm>",
"methods": {},
"title": "Proxied - indicates that a contract will be proxied. Also defines storage requirements for Proxy."
},
"userdoc": {
"methods": {}
}
}

1006
build/contracts/Proxy.json Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1865
build/contracts/Token.json Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,6 @@
pragma solidity ^0.5.2;
import "../src/test/contracts/TokenOMG.sol";
import "../src/test/contracts/TokenRDN.sol";
contract DevDependenciesGetter {}

23
contracts/Migrations.sol Normal file
View File

@ -0,0 +1,23 @@
pragma solidity ^0.5.2;
contract Migrations {
address public owner;
uint public last_completed_migration;
modifier restricted() {
if (msg.sender == owner) _;
}
constructor () public {
owner = msg.sender;
}
function setCompleted(uint completed) public restricted {
last_completed_migration = completed;
}
function upgrade(address new_address) public restricted {
Migrations upgraded = Migrations(new_address);
upgraded.setCompleted(last_completed_migration);
}
}

View File

@ -14,7 +14,7 @@ module.exports = {
'<rootDir>/config/jest/LocalStorageMock.js', '<rootDir>/config/jest/LocalStorageMock.js',
'<rootDir>/config/jest/Web3Mock.js', '<rootDir>/config/jest/Web3Mock.js',
], ],
setupFilesAfterEnv: ['<rootDir>/config/jest/jest.setup.js', 'react-testing-library/cleanup-after-each'], setupFilesAfterEnv: ['<rootDir>/config/jest/jest.setup.js', '@testing-library/react/cleanup-after-each'],
testEnvironment: 'node', testEnvironment: 'node',
testMatch: ['<rootDir>/src/**/__tests__/**/*.js?(x)', '<rootDir>/src/**/?(*.)(spec|test).js?(x)'], testMatch: ['<rootDir>/src/**/__tests__/**/*.js?(x)', '<rootDir>/src/**/?(*.)(spec|test).js?(x)'],
testURL: 'http://localhost:8000', testURL: 'http://localhost:8000',

View File

@ -0,0 +1,4 @@
// @flow
const Migrations = artifacts.require('./Migrations.sol')
module.exports = deployer => deployer.deploy(Migrations)

View File

@ -0,0 +1,21 @@
// @flow
/* eslint-disable no-console */
const TokenOMG = artifacts.require('TokenOMG')
const TokenRDN = artifacts.require('TokenRDN')
module.exports = (deployer, network) => {
let toBN
if (typeof web3.version === 'string') {
// 1.X.xx Web3
({ toBN } = web3.utils)
} else {
toBN = web3.toBigNumber
}
if (network === 'development') {
return deployer
.deploy(TokenOMG, toBN(50000).mul(toBN(10).pow(toBN(18))))
.then(() => deployer.deploy(TokenRDN, toBN(50000).mul(toBN(10).pow(toBN(18)))))
}
return console.log('Not running on development, skipping.')
}

View File

@ -35,7 +35,7 @@
"@material-ui/core": "4.0.1", "@material-ui/core": "4.0.1",
"@material-ui/icons": "4.0.1", "@material-ui/icons": "4.0.1",
"@welldone-software/why-did-you-render": "^3.0.9", "@welldone-software/why-did-you-render": "^3.0.9",
"axios": "^0.18.0", "axios": "0.19.0",
"bignumber.js": "9.0.0", "bignumber.js": "9.0.0",
"connected-react-router": "^6.3.1", "connected-react-router": "^6.3.1",
"final-form": "4.13.0", "final-form": "4.13.0",
@ -47,7 +47,7 @@
"qrcode.react": "^0.9.3", "qrcode.react": "^0.9.3",
"react": "^16.8.6", "react": "^16.8.6",
"react-dom": "^16.8.6", "react-dom": "^16.8.6",
"react-final-form": "6.0.0", "react-final-form": "6.0.1",
"react-final-form-listeners": "^1.0.2", "react-final-form-listeners": "^1.0.2",
"react-hot-loader": "4.8.8", "react-hot-loader": "4.8.8",
"react-infinite-scroll-component": "^4.5.2", "react-infinite-scroll-component": "^4.5.2",
@ -90,6 +90,7 @@
"@storybook/addon-knobs": "5.0.11", "@storybook/addon-knobs": "5.0.11",
"@storybook/addon-links": "5.0.11", "@storybook/addon-links": "5.0.11",
"@storybook/react": "5.0.11", "@storybook/react": "5.0.11",
"@testing-library/react": "^8.0.1",
"autoprefixer": "9.5.1", "autoprefixer": "9.5.1",
"babel-core": "^7.0.0-bridge.0", "babel-core": "^7.0.0-bridge.0",
"babel-eslint": "^10.0.1", "babel-eslint": "^10.0.1",
@ -111,7 +112,7 @@
"ethereumjs-abi": "^0.6.7", "ethereumjs-abi": "^0.6.7",
"extract-text-webpack-plugin": "^4.0.0-beta.0", "extract-text-webpack-plugin": "^4.0.0-beta.0",
"file-loader": "^3.0.1", "file-loader": "^3.0.1",
"flow-bin": "0.99.0", "flow-bin": "0.99.1",
"fs-extra": "8.0.1", "fs-extra": "8.0.1",
"html-loader": "^0.5.5", "html-loader": "^0.5.5",
"html-webpack-plugin": "^3.0.4", "html-webpack-plugin": "^3.0.4",
@ -123,14 +124,13 @@
"postcss-simple-vars": "^5.0.2", "postcss-simple-vars": "^5.0.2",
"pre-commit": "^1.2.2", "pre-commit": "^1.2.2",
"prettier-eslint-cli": "^4.7.1", "prettier-eslint-cli": "^4.7.1",
"react-testing-library": "^7.0.1",
"run-with-testrpc": "0.3.1", "run-with-testrpc": "0.3.1",
"storybook-host": "^5.0.3", "storybook-host": "^5.0.3",
"storybook-router": "^0.3.3", "storybook-router": "^0.3.3",
"style-loader": "^0.23.1", "style-loader": "^0.23.1",
"truffle": "5.0.19", "truffle": "5.0.20",
"truffle-contract": "4.0.17", "truffle-contract": "4.0.18",
"truffle-solidity-loader": "0.1.18", "truffle-solidity-loader": "0.1.19",
"uglifyjs-webpack-plugin": "2.1.3", "uglifyjs-webpack-plugin": "2.1.3",
"webpack": "4.32.2", "webpack": "4.32.2",
"webpack-bundle-analyzer": "3.3.2", "webpack-bundle-analyzer": "3.3.2",

View File

@ -35,6 +35,23 @@ yarn start
## Running the tests ## Running the tests
To run the test, you'll need to migrate contracts `safe-contracts` to the local ganache-cli
1. Migrating Safe Contracts:
```
git clone https://github.com/gnosis/safe-contracts.git
cd safe-contracts
yarn
ganache-cli -l 7000000
npx truffle compile
npx truffle migrate
```
2. Compiling Token Contracts for the tests:
Inside `safe-react` directory
```
npx truffle compile
```
3. Run the tests:
``` ```
yarn test yarn test
``` ```

View File

@ -1,6 +1,5 @@
// @flow // @flow
import * as React from 'react' import * as React from 'react'
import contract from 'truffle-contract'
import { withStyles } from '@material-ui/core/styles' import { withStyles } from '@material-ui/core/styles'
import Field from '~/components/forms/Field' import Field from '~/components/forms/Field'
import { import {

View File

@ -154,7 +154,7 @@ class Balances extends React.Component<Props, State> {
defaultFixed defaultFixed
> >
{(sortedData: Array<BalanceRow>) => sortedData.map((row: any, index: number) => ( {(sortedData: Array<BalanceRow>) => sortedData.map((row: any, index: number) => (
<TableRow tabIndex={-1} key={index} className={classes.hide}> <TableRow tabIndex={-1} key={index} className={classes.hide} data-testid="balance-row">
{autoColumns.map((column: Column) => ( {autoColumns.map((column: Column) => (
<TableCell key={column.id} style={cellWidth(column.width)} align={column.align} component="td"> <TableCell key={column.id} style={cellWidth(column.width)} align={column.align} component="td">
{column.id === BALANCE_TABLE_ASSET_ID ? <AssetTableCell asset={row[column.id]} /> : row[column.id]} {column.id === BALANCE_TABLE_ASSET_ID ? <AssetTableCell asset={row[column.id]} /> : row[column.id]}
@ -169,6 +169,7 @@ class Balances extends React.Component<Props, State> {
color="secondary" color="secondary"
className={classes.send} className={classes.send}
onClick={() => this.showSendFunds(row.asset.name)} onClick={() => this.showSendFunds(row.asset.name)}
data-testid="balance-send-btn"
> >
<CallMade className={classNames(classes.leftIcon, classes.iconSmall)} /> <CallMade className={classNames(classes.leftIcon, classes.iconSmall)} />
Send Send

View File

@ -5,9 +5,9 @@ import SafeView from '~/routes/safe/components/Safe'
import { aNewStore, type GlobalState } from '~/store' import { aNewStore, type GlobalState } from '~/store'
import { sleep } from '~/utils/timer' import { sleep } from '~/utils/timer'
import { getWeb3 } from '~/logic/wallets/getWeb3' import { getWeb3 } from '~/logic/wallets/getWeb3'
import { addEtherTo } from '~/test/utils/tokenMovements' import { sendEtherTo } from '~/test/utils/tokenMovements'
import { aMinedSafe } from '~/test/builder/safe.redux.builder' import { aMinedSafe } from '~/test/builder/safe.redux.builder'
import { travelToSafe } from '~/test/builder/safe.dom.utils' import { renderSafeView } from '~/test/builder/safe.dom.utils'
import { MOVE_FUNDS_BUTTON_TEXT } from '~/routes/safe/components/Safe/BalanceInfo' import { MOVE_FUNDS_BUTTON_TEXT } from '~/routes/safe/components/Safe/BalanceInfo'
export type DomSafe = { export type DomSafe = {
@ -30,10 +30,10 @@ export const renderSafeInDom = async (owners: number = 1, threshold: number = 1)
// have available accounts // have available accounts
const accounts = await getWeb3().eth.getAccounts() const accounts = await getWeb3().eth.getAccounts()
// navigate to SAFE route // navigate to SAFE route
const SafeDom = travelToSafe(store, address) const SafeDom = renderSafeView(store, address)
// add funds to safe // add funds to safe
await addEtherTo(address, '0.1') await sendEtherTo(address, '0.1')
// wait until funds are displayed and buttons are enabled // wait until funds are displayed and buttons are enabled
await sleep(3000) await sleep(3000)

View File

@ -1,6 +1,7 @@
// @flow // @flow
import * as React from 'react' import * as React from 'react'
import TestUtils from 'react-dom/test-utils' import TestUtils from 'react-dom/test-utils'
import { render } from '@testing-library/react'
import ListItemText from '~/components/List/ListItemText/index' import ListItemText from '~/components/List/ListItemText/index'
import { SEE_MULTISIG_BUTTON_TEXT } from '~/routes/safe/components/Safe/MultisigTx' import { SEE_MULTISIG_BUTTON_TEXT } from '~/routes/safe/components/Safe/MultisigTx'
import fetchTransactions from '~/routes/safe/store/actions/fetchTransactions' import fetchTransactions from '~/routes/safe/store/actions/fetchTransactions'
@ -92,7 +93,7 @@ export const refreshTransactions = async (store: Store<GlobalState>, safeAddress
await sleep(1500) await sleep(1500)
} }
const createDom = (store: Store): React$Component<{}> => TestUtils.renderIntoDocument( const renderApp = (store: Store) => render(
<Provider store={store}> <Provider store={store}>
<ConnectedRouter history={history}> <ConnectedRouter history={history}>
<AppRoutes /> <AppRoutes />
@ -100,17 +101,17 @@ const createDom = (store: Store): React$Component<{}> => TestUtils.renderIntoDoc
</Provider>, </Provider>,
) )
export const travelToSafe = (store: Store, address: string): React$Component<{}> => { export const renderSafeView = (store: Store, address: string) => {
history.push(`${SAFELIST_ADDRESS}/${address}`) history.push(`${SAFELIST_ADDRESS}/${address}`)
return createDom(store) return renderApp(store)
} }
export const travelToTokens = (store: Store, address: string): React$Component<{}> => { export const travelToTokens = (store: Store, address: string): React$Component<{}> => {
const url = `${SAFELIST_ADDRESS}/${address}${SETTINS_ADDRESS}` const url = `${SAFELIST_ADDRESS}/${address}${SETTINS_ADDRESS}`
history.push(url) history.push(url)
return createDom(store) return renderApp(store)
} }
const INTERVAL = 500 const INTERVAL = 500

View File

@ -0,0 +1,17 @@
pragma solidity ^0.5.2;
import "@gnosis.pm/util-contracts/contracts/GnosisStandardToken.sol";
contract TokenOMG is GnosisStandardToken {
string public constant symbol = "OMG";
string public constant name = "Omisego Token";
uint8 public constant decimals = 18;
constructor(
uint amount
)
public
{
balances[msg.sender] = amount;
}
}

View File

@ -0,0 +1,17 @@
pragma solidity ^0.5.2;
import "@gnosis.pm/util-contracts/contracts/GnosisStandardToken.sol";
contract TokenRDN is GnosisStandardToken {
string public constant symbol = "RDN";
string public constant name = "Raiden Token";
uint8 public constant decimals = 18;
constructor(
uint amount
)
public
{
balances[msg.sender] = amount;
}
}

View File

@ -1,7 +1,7 @@
// @flow // @flow
import * as React from 'react' import * as React from 'react'
import { type Store } from 'redux' import { type Store } from 'redux'
import { render, fireEvent, cleanup } from 'react-testing-library' import { render, fireEvent, cleanup } from '@testing-library/react'
import { Provider } from 'react-redux' import { Provider } from 'react-redux'
import { ConnectedRouter } from 'connected-react-router' import { ConnectedRouter } from 'connected-react-router'
import { ADD_OWNER_BUTTON } from '~/routes/open/components/SafeOwnersForm' import { ADD_OWNER_BUTTON } from '~/routes/open/components/SafeOwnersForm'
@ -16,7 +16,7 @@ import { whenSafeDeployed } from './builder/safe.dom.utils'
afterEach(cleanup) afterEach(cleanup)
// https://github.com/testing-library/react-testing-library/issues/281 // https://github.com/testing-library/@testing-library/react/issues/281
const originalError = console.error const originalError = console.error
beforeAll(() => { beforeAll(() => {
console.error = (...args) => { console.error = (...args) => {

View File

@ -1,16 +1,17 @@
// @flow // @flow
import { render, fireEvent, cleanup } from '@testing-library/react'
import TestUtils from 'react-dom/test-utils'
import * as fetchBalancesAction from '~/logic/tokens/store/actions/fetchTokens' import * as fetchBalancesAction from '~/logic/tokens/store/actions/fetchTokens'
import { aNewStore } from '~/store' import { aNewStore } from '~/store'
import { aMinedSafe } from '~/test/builder/safe.redux.builder' import { aMinedSafe } from '~/test/builder/safe.redux.builder'
import { addTknTo, getFirstTokenContract } from '~/test/utils/tokenMovements' import { sendTokenTo, getFirstTokenContract } from '~/test/utils/tokenMovements'
import { EXPAND_BALANCE_INDEX, travelToSafe } from '~/test/builder/safe.dom.utils' import { EXPAND_BALANCE_INDEX, renderSafeView } from '~/test/builder/safe.dom.utils'
import { getWeb3 } from '~/logic/wallets/getWeb3' import { getWeb3 } from '~/logic/wallets/getWeb3'
import { sendMoveTokensForm, dispatchTknBalance } from '~/test/utils/transactions/moveTokens.helper' import { sendMoveTokensForm, dispatchTknBalance } from '~/test/utils/transactions/moveTokens.helper'
import { sleep } from '~/utils/timer' import { sleep } from '~/utils/timer'
describe('DOM > Feature > SAFE ERC20 TOKENS', () => { afterEach(cleanup)
describe('DOM > Feature > Funds', () => {
let store let store
let safeAddress: string let safeAddress: string
let accounts let accounts
@ -20,10 +21,10 @@ describe('DOM > Feature > SAFE ERC20 TOKENS', () => {
accounts = await getWeb3().eth.getAccounts() accounts = await getWeb3().eth.getAccounts()
}) })
it('sends ERC20 tokens', async () => { it('Sends ETH', async () => {
// GIVEN // GIVEN
const numTokens = '100' const numTokens = '100'
const tokenAddress = await addTknTo(safeAddress, numTokens) const tokenAddress = await sendTokenTo(safeAddress, numTokens)
await dispatchTknBalance(store, tokenAddress, safeAddress) await dispatchTknBalance(store, tokenAddress, safeAddress)
// const StandardToken = await fetchBalancesAction.getStandardTokenContract() // const StandardToken = await fetchBalancesAction.getStandardTokenContract()
@ -32,7 +33,39 @@ describe('DOM > Feature > SAFE ERC20 TOKENS', () => {
// console.log(await myToken.balanceOf(safeAddress)) // console.log(await myToken.balanceOf(safeAddress))
// WHEN // WHEN
const SafeDom = await travelToSafe(store, safeAddress) const SafeDom = await renderSafeView(store, safeAddress)
await sleep(800)
const balanceRows = SafeDom.getAllByTestId('balance-row')
const buttons = TestUtils.scryRenderedDOMComponentsWithTag(SafeDom, 'button')
const expandBalance = buttons[EXPAND_BALANCE_INDEX]
const receiver = accounts[2]
await sendMoveTokensForm(SafeDom, expandBalance, 20, accounts[2])
// THEN
const safeFunds = await fetchBalancesAction.calculateBalanceOf(tokenAddress, safeAddress, 18)
expect(Number(safeFunds)).toBe(80)
const receiverFunds = await fetchBalancesAction.calculateBalanceOf(tokenAddress, receiver, 18)
expect(Number(receiverFunds)).toBe(20)
const token = await getFirstTokenContract(getWeb3(), accounts[0])
const nativeSafeFunds = await token.balanceOf(safeAddress)
expect(Number(nativeSafeFunds.valueOf())).toEqual(80 * 10 ** 18)
})
it('Sends Tokens', async () => {
// GIVEN
const numTokens = '100'
const tokenAddress = await sendTokenTo(safeAddress, numTokens)
await dispatchTknBalance(store, tokenAddress, safeAddress)
// const StandardToken = await fetchBalancesAction.getStandardTokenContract()
// const myToken = await StandardToken.at(tokenAddress)
// console.log(await myToken.allowance(safeAddress, accounts[2]))
// console.log(await myToken.balanceOf(safeAddress))
// WHEN
const SafeDom = await renderSafeView(store, safeAddress)
await sleep(800) await sleep(800)
// $FlowFixMe // $FlowFixMe
const buttons = TestUtils.scryRenderedDOMComponentsWithTag(SafeDom, 'button') const buttons = TestUtils.scryRenderedDOMComponentsWithTag(SafeDom, 'button')
@ -50,25 +83,4 @@ describe('DOM > Feature > SAFE ERC20 TOKENS', () => {
const nativeSafeFunds = await token.balanceOf(safeAddress) const nativeSafeFunds = await token.balanceOf(safeAddress)
expect(Number(nativeSafeFunds.valueOf())).toEqual(80 * 10 ** 18) expect(Number(nativeSafeFunds.valueOf())).toEqual(80 * 10 ** 18)
}) })
it('disables send token button when balance is 0', async () => {
// GIVEN
const token = await getFirstTokenContract(getWeb3(), accounts[0])
await dispatchTknBalance(store, token.address, safeAddress)
// WHEN
const SafeDom = travelToSafe(store, safeAddress)
// $FlowFixMe
const buttons = TestUtils.scryRenderedDOMComponentsWithTag(SafeDom, 'button')
const expandBalance = buttons[EXPAND_BALANCE_INDEX]
TestUtils.Simulate.click(expandBalance)
await sleep(800)
// $FlowFixMe
const balanceButtons = TestUtils.scryRenderedDOMComponentsWithTag(SafeDom, 'button')
const tokenButton = balanceButtons[EXPAND_BALANCE_INDEX + 1] // expand button, and the next one is for sending
expect(tokenButton.hasAttribute('disabled')).toBe(true)
})
}) })

View File

@ -2,7 +2,7 @@
import * as React from 'react' import * as React from 'react'
import { type Store } from 'redux' import { type Store } from 'redux'
import { Provider } from 'react-redux' import { Provider } from 'react-redux'
import { render, fireEvent, cleanup } from 'react-testing-library' import { render, fireEvent, cleanup } from '@testing-library/react'
import { ConnectedRouter } from 'connected-react-router' import { ConnectedRouter } from 'connected-react-router'
import Load from '~/routes/load/container/Load' import Load from '~/routes/load/container/Load'
import { aNewStore, history, type GlobalState } from '~/store' import { aNewStore, history, type GlobalState } from '~/store'
@ -15,7 +15,7 @@ import { whenSafeDeployed } from './builder/safe.dom.utils'
afterEach(cleanup) afterEach(cleanup)
// https://github.com/testing-library/react-testing-library/issues/281 // https://github.com/testing-library/@testing-library/react/issues/281
const originalError = console.error const originalError = console.error
beforeAll(() => { beforeAll(() => {
console.error = (...args) => { console.error = (...args) => {

View File

@ -5,7 +5,7 @@ import { aNewStore } from '~/store'
import { aMinedSafe } from '~/test/builder/safe.redux.builder' import { aMinedSafe } from '~/test/builder/safe.redux.builder'
import { type Token } from '~/logic/tokens/store/model/token' import { type Token } from '~/logic/tokens/store/model/token'
import { TOKEN_REDUCER_ID } from '~/logic/tokens/store/reducer/tokens' import { TOKEN_REDUCER_ID } from '~/logic/tokens/store/reducer/tokens'
import { addEtherTo, addTknTo } from '~/test/utils/tokenMovements' import { sendEtherTo, sendTokenTo } from '~/test/utils/tokenMovements'
import { dispatchTknBalance } from '~/test/utils/transactions/moveTokens.helper' import { dispatchTknBalance } from '~/test/utils/transactions/moveTokens.helper'
import { ETH_ADDRESS } from '~/logic/tokens/utils/tokenHelpers' import { ETH_ADDRESS } from '~/logic/tokens/utils/tokenHelpers'
@ -38,7 +38,7 @@ describe('Safe - redux balance property', () => {
it('reducer should return 0.03456 ETH as funds to safe with 0.03456 ETH', async () => { it('reducer should return 0.03456 ETH as funds to safe with 0.03456 ETH', async () => {
// WHEN // WHEN
await addEtherTo(address, '0.03456') await sendEtherTo(address, '0.03456')
await store.dispatch(fetchTokensAction.fetchTokens(address)) await store.dispatch(fetchTokensAction.fetchTokens(address))
// THEN // THEN
@ -57,7 +57,7 @@ describe('Safe - redux balance property', () => {
it('reducer should return 100 TKN when safe has 100 TKN', async () => { it('reducer should return 100 TKN when safe has 100 TKN', async () => {
// GIVEN // GIVEN
const numTokens = '100' const numTokens = '100'
const tokenAddress = await addTknTo(address, numTokens) const tokenAddress = await sendTokenTo(address, numTokens)
// WHEN // WHEN
await dispatchTknBalance(store, tokenAddress, address) await dispatchTknBalance(store, tokenAddress, address)

View File

@ -4,7 +4,7 @@ import { List } from 'immutable'
import { getWeb3 } from '~/logic/wallets/getWeb3' import { getWeb3 } from '~/logic/wallets/getWeb3'
import { type Match } from 'react-router-dom' import { type Match } from 'react-router-dom'
import Checkbox from '@material-ui/core/Checkbox' import Checkbox from '@material-ui/core/Checkbox'
import { getFirstTokenContract, getSecondTokenContract, addTknTo } from '~/test/utils/tokenMovements' import { getFirstTokenContract, getSecondTokenContract, sendTokenTo } from '~/test/utils/tokenMovements'
import { aNewStore } from '~/store' import { aNewStore } from '~/store'
import { aMinedSafe } from '~/test/builder/safe.redux.builder' import { aMinedSafe } from '~/test/builder/safe.redux.builder'
import { travelToTokens } from '~/test/builder/safe.dom.utils' import { travelToTokens } from '~/test/builder/safe.dom.utils'
@ -76,8 +76,8 @@ describe('DOM > Feature > Enable and disable default tokens', () => {
// GIVEN // GIVEN
const store = aNewStore() const store = aNewStore()
const safeAddress = await aMinedSafe(store) const safeAddress = await aMinedSafe(store)
await addTknTo(safeAddress, '50', firstErc20Token) await sendTokenTo(safeAddress, '50', firstErc20Token)
await addTknTo(safeAddress, '50', secondErc20Token) await sendTokenTo(safeAddress, '50', secondErc20Token)
await store.dispatch(fetchTokensModule.fetchTokens(safeAddress)) await store.dispatch(fetchTokensModule.fetchTokens(safeAddress))
const match: Match = buildMathPropsFrom(safeAddress) const match: Match = buildMathPropsFrom(safeAddress)

View File

@ -4,7 +4,7 @@ import { type Match } from 'react-router-dom'
import { getFirstTokenContract, getSecondTokenContract } from '~/test/utils/tokenMovements' import { getFirstTokenContract, getSecondTokenContract } from '~/test/utils/tokenMovements'
import { aNewStore } from '~/store' import { aNewStore } from '~/store'
import { aMinedSafe } from '~/test/builder/safe.redux.builder' import { aMinedSafe } from '~/test/builder/safe.redux.builder'
import { travelToSafe } from '~/test/builder/safe.dom.utils' import { renderSafeView } from '~/test/builder/safe.dom.utils'
import { buildMathPropsFrom } from '~/test/utils/buildReactRouterProps' import { buildMathPropsFrom } from '~/test/utils/buildReactRouterProps'
import { testToken } from '~/test/builder/tokens.dom.utils' import { testToken } from '~/test/builder/tokens.dom.utils'
import * as fetchTokensModule from '~/logic/tokens/store/actions/fetchTokens' import * as fetchTokensModule from '~/logic/tokens/store/actions/fetchTokens'
@ -49,11 +49,11 @@ describe('DOM > Feature > Add new ERC 20 Tokens', () => {
// } // }
// const customAddTokensFn: any = (...args) => store.dispatch(addToken(...args)) // const customAddTokensFn: any = (...args) => store.dispatch(addToken(...args))
// await addTokenFnc(values, customAddTokensFn, safeAddress) // await addTokenFnc(values, customAddTokensFn, safeAddress)
// travelToSafe(store, safeAddress) // renderSafeView(store, safeAddress)
// // WHEN // // WHEN
// const reloadedStore = aNewStore() // const reloadedStore = aNewStore()
// await reloadedStore.dispatch(fetchTokensModule.fetchTokens(safeAddress)) // await reloadedStore.dispatch(fetchTokensModule.fetchTokens(safeAddress))
// travelToSafe(reloadedStore, safeAddress) // reload // renderSafeView(reloadedStore, safeAddress) // reload
// // THEN // // THEN
// const match: Match = buildMathPropsFrom(safeAddress) // const match: Match = buildMathPropsFrom(safeAddress)
// const activeTokenList = activeTokensSelector(reloadedStore.getState(), { match }) // const activeTokenList = activeTokensSelector(reloadedStore.getState(), { match })

View File

@ -4,7 +4,7 @@ import { type Match } from 'react-router-dom'
import { getFirstTokenContract, getSecondTokenContract } from '~/test/utils/tokenMovements' import { getFirstTokenContract, getSecondTokenContract } from '~/test/utils/tokenMovements'
import { aNewStore } from '~/store' import { aNewStore } from '~/store'
import { aMinedSafe } from '~/test/builder/safe.redux.builder' import { aMinedSafe } from '~/test/builder/safe.redux.builder'
import { travelToSafe } from '~/test/builder/safe.dom.utils' import { renderSafeView } from '~/test/builder/safe.dom.utils'
import { buildMathPropsFrom } from '~/test/utils/buildReactRouterProps' import { buildMathPropsFrom } from '~/test/utils/buildReactRouterProps'
import { testToken } from '~/test/builder/tokens.dom.utils' import { testToken } from '~/test/builder/tokens.dom.utils'
import * as fetchTokensModule from '~/logic/tokens/store/actions/fetchTokens' import * as fetchTokensModule from '~/logic/tokens/store/actions/fetchTokens'
@ -76,7 +76,7 @@ describe('DOM > Feature > Add new ERC 20 Tokens', () => {
// // WHEN // // WHEN
// const reloadedStore = aNewStore() // const reloadedStore = aNewStore()
// await reloadedStore.dispatch(fetchTokensModule.fetchTokens(safeAddress)) // await reloadedStore.dispatch(fetchTokensModule.fetchTokens(safeAddress))
// travelToSafe(reloadedStore, safeAddress) // reload // renderSafeView(reloadedStore, safeAddress) // reload
// // THEN // // THEN
// checkTokensOf(reloadedStore, safeAddress) // checkTokensOf(reloadedStore, safeAddress)
// }) // })

View File

@ -1,11 +1,12 @@
// @flow // @flow
import contract from 'truffle-contract' import contract from 'truffle-contract'
import { getBalanceInEtherOf, getWeb3 } from '~/logic/wallets/getWeb3' import { getBalanceInEtherOf, getWeb3 } from '~/logic/wallets/getWeb3'
import Token from '#/test/TestToken.json'
import { ensureOnce } from '~/utils/singleton' import { ensureOnce } from '~/utils/singleton'
import { toNative } from '~/logic/wallets/tokens' import { toNative } from '~/logic/wallets/tokens'
import TokenOMG from '../../../build/contracts/TokenOMG'
import TokenRDN from '../../../build/contracts/TokenRDN'
export const addEtherTo = async (address: string, eth: string) => { export const sendEtherTo = async (address: string, eth: string) => {
const web3 = getWeb3() const web3 = getWeb3()
const accounts = await web3.eth.getAccounts() const accounts = await web3.eth.getAccounts()
const txData = { from: accounts[0], to: address, value: web3.utils.toWei(eth, 'ether') } const txData = { from: accounts[0], to: address, value: web3.utils.toWei(eth, 'ether') }
@ -17,23 +18,34 @@ export const checkBalanceOf = async (addressToTest: string, value: string) => {
expect(safeBalance).toBe(value) expect(safeBalance).toBe(value)
} }
const createTokenContract = async (web3: any, executor: string) => { const createTokenOMGContract = async (web3: any, creator: string) => {
const token = contract(Token) const token = contract(TokenOMG)
const { toBN } = web3.utils
const amount = toBN(50000).mul(toBN(10).pow(toBN(18))).toString()
token.setProvider(web3.currentProvider) token.setProvider(web3.currentProvider)
return token.new({ from: executor, gas: '5000000' }) return token.new(amount, { from: creator })
} }
export const getFirstTokenContract = ensureOnce(createTokenContract) const createTokenRDNContract = async (web3: any, creator: string) => {
export const getSecondTokenContract = ensureOnce(createTokenContract) const token = contract(TokenRDN)
const { toBN } = web3.utils
const amount = toBN(50000).mul(toBN(10).pow(toBN(18))).toString()
token.setProvider(web3.currentProvider)
export const addTknTo = async (safe: string, value: string, tokenContract?: any) => { return token.new(amount, { from: creator })
}
export const getFirstTokenContract = ensureOnce(createTokenOMGContract)
export const getSecondTokenContract = ensureOnce(createTokenRDNContract)
export const sendTokenTo = async (safe: string, value: string, tokenContract?: any) => {
const web3 = getWeb3() const web3 = getWeb3()
const accounts = await web3.eth.getAccounts() const accounts = await web3.eth.getAccounts()
const myToken = tokenContract || (await getFirstTokenContract(web3, accounts[0])) const OMGToken = tokenContract || (await getFirstTokenContract(web3, accounts[0]))
const nativeValue = toNative(value, 18) const nativeValue = toNative(value, 18)
await myToken.transfer(safe, nativeValue.valueOf(), { from: accounts[0], gas: '5000000' }) await OMGToken.transfer(safe, nativeValue.valueOf(), { from: accounts[0], gas: '5000000' })
return myToken.address return OMGToken.address
} }

View File

@ -1,16 +1,18 @@
// @flow
module.exports = { module.exports = {
migrations_directory: "./migrations", migrations_directory: './migrations',
networks: { networks: {
development: { development: {
host: "localhost", host: 'localhost',
port: 8545, port: 8545,
network_id: "*" //* Match any network id network_id: '*', //* Match any network id
} },
}, },
solc: { solc: {
optimizer: { optimizer: {
enabled: true, enabled: true,
runs: 500 runs: 500,
} },
} },
}; }

2805
yarn.lock

File diff suppressed because it is too large Load Diff