Merge pull request #27 from gnosis/feature/WA-238-load-safes-by-owner

WA-238 Load safes by owner
This commit is contained in:
Adolfo Panizo 2018-05-23 08:34:18 +02:00 committed by GitHub
commit b784316cfa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
40 changed files with 28982 additions and 17351 deletions

View File

@ -77,6 +77,8 @@ module.exports = {
bail: true,
optimization: {
splitChunks: {
chunks: "all",
/* https://stackoverflow.com/questions/48985780/webpack-4-create-vendor-chunk
cacheGroups: {
vendor: {
test: /node_modules/,
@ -86,6 +88,7 @@ module.exports = {
minSize: 1,
},
},
*/
},
},
entry: [

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

@ -3,29 +3,29 @@
"abi": [],
"bytecode": "0x6080604052348015600f57600080fd5b50603580601d6000396000f3006080604052600080fd00a165627a7a72305820346c40fd38e691d9042d78bf7c33e05e8eafc3767b153318d8f2a9f5daf08bcf0029",
"deployedBytecode": "0x6080604052600080fd00a165627a7a72305820346c40fd38e691d9042d78bf7c33e05e8eafc3767b153318d8f2a9f5daf08bcf0029",
"sourceMap": "115:95:1:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;115:95:1;;;;;;;",
"deployedSourceMap": "115:95:1:-;;;;;",
"sourceMap": "115:95:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;115:95:0;;;;;;;",
"deployedSourceMap": "115:95:0:-;;;;;",
"source": "pragma solidity 0.4.23;\n\n\n/// @title Enum - Collection of enums\n/// @author Richard Meissner - <richard@gnosis.pm>\ncontract Enum {\n enum Operation {\n Call,\n DelegateCall,\n Create\n }\n}\n",
"sourcePath": "/Users/apanizo/git/gnosis/safe-contracts/contracts/Enum.sol",
"ast": {
"absolutePath": "/Users/apanizo/git/gnosis/safe-contracts/contracts/Enum.sol",
"exportedSymbols": {
"Enum": [
30
6
]
},
"id": 31,
"id": 7,
"nodeType": "SourceUnit",
"nodes": [
{
"id": 25,
"id": 1,
"literals": [
"solidity",
"0.4",
".23"
],
"nodeType": "PragmaDirective",
"src": "0:23:1"
"src": "0:23:0"
},
{
"baseContracts": [],
@ -33,66 +33,66 @@
"contractKind": "contract",
"documentation": "@title Enum - Collection of enums\n @author Richard Meissner - <richard@gnosis.pm>",
"fullyImplemented": true,
"id": 30,
"id": 6,
"linearizedBaseContracts": [
30
6
],
"name": "Enum",
"nodeType": "ContractDefinition",
"nodes": [
{
"canonicalName": "Enum.Operation",
"id": 29,
"id": 5,
"members": [
{
"id": 26,
"id": 2,
"name": "Call",
"nodeType": "EnumValue",
"src": "160:4:1"
"src": "160:4:0"
},
{
"id": 27,
"id": 3,
"name": "DelegateCall",
"nodeType": "EnumValue",
"src": "174:12:1"
"src": "174:12:0"
},
{
"id": 28,
"id": 4,
"name": "Create",
"nodeType": "EnumValue",
"src": "196:6:1"
"src": "196:6:0"
}
],
"name": "Operation",
"nodeType": "EnumDefinition",
"src": "135:73:1"
"src": "135:73:0"
}
],
"scope": 31,
"src": "115:95:1"
"scope": 7,
"src": "115:95:0"
}
],
"src": "0:211:1"
"src": "0:211:0"
},
"legacyAST": {
"absolutePath": "/Users/apanizo/git/gnosis/safe-contracts/contracts/Enum.sol",
"exportedSymbols": {
"Enum": [
30
6
]
},
"id": 31,
"id": 7,
"nodeType": "SourceUnit",
"nodes": [
{
"id": 25,
"id": 1,
"literals": [
"solidity",
"0.4",
".23"
],
"nodeType": "PragmaDirective",
"src": "0:23:1"
"src": "0:23:0"
},
{
"baseContracts": [],
@ -100,46 +100,46 @@
"contractKind": "contract",
"documentation": "@title Enum - Collection of enums\n @author Richard Meissner - <richard@gnosis.pm>",
"fullyImplemented": true,
"id": 30,
"id": 6,
"linearizedBaseContracts": [
30
6
],
"name": "Enum",
"nodeType": "ContractDefinition",
"nodes": [
{
"canonicalName": "Enum.Operation",
"id": 29,
"id": 5,
"members": [
{
"id": 26,
"id": 2,
"name": "Call",
"nodeType": "EnumValue",
"src": "160:4:1"
"src": "160:4:0"
},
{
"id": 27,
"id": 3,
"name": "DelegateCall",
"nodeType": "EnumValue",
"src": "174:12:1"
"src": "174:12:0"
},
{
"id": 28,
"id": 4,
"name": "Create",
"nodeType": "EnumValue",
"src": "196:6:1"
"src": "196:6:0"
}
],
"name": "Operation",
"nodeType": "EnumDefinition",
"src": "135:73:1"
"src": "135:73:0"
}
],
"scope": 31,
"src": "115:95:1"
"scope": 7,
"src": "115:95:0"
}
],
"src": "0:211:1"
"src": "0:211:0"
},
"compiler": {
"name": "solc",
@ -147,5 +147,5 @@
},
"networks": {},
"schemaVersion": "2.0.0",
"updatedAt": "2018-05-10T10:43:07.892Z"
"updatedAt": "2018-05-16T10:51:14.736Z"
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -18,38 +18,38 @@
],
"bytecode": "0x608060405234801561001057600080fd5b50610158806100206000396000f300608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680637de7edef14610046575b600080fd5b34801561005257600080fd5b50610087600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610089565b005b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156100c357600080fd5b60008173ffffffffffffffffffffffffffffffffffffffff16141515156100e957600080fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505600a165627a7a7230582073cd5ab8858f9d67e5e09748f71ecf939357d0d1230776e9f935b1ef5d664eb00029",
"deployedBytecode": "0x608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680637de7edef14610046575b600080fd5b34801561005257600080fd5b50610087600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610089565b005b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156100c357600080fd5b60008173ffffffffffffffffffffffffffffffffffffffff16141515156100e957600080fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550505600a165627a7a7230582073cd5ab8858f9d67e5e09748f71ecf939357d0d1230776e9f935b1ef5d664eb00029",
"sourceMap": "203:633:6:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;203:633:6;;;;;;;",
"deployedSourceMap": "203:633:6:-;;;;;;;;;;;;;;;;;;;;;;;;626:208;;8:9:-1;5:2;;;30:1;27;20:12;5:2;626:208:6;;;;;;;;;;;;;;;;;;;;;;;;;;;;;244:4:14;222:27;;:10;:27;;;214:36;;;;;;;;791:1:6;776:11;:16;;;;768:25;;;;;;;;816:11;803:10;;:24;;;;;;;;;;;;;;;;;;626:208;:::o",
"sourceMap": "203:633:4:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;203:633:4;;;;;;;",
"deployedSourceMap": "203:633:4:-;;;;;;;;;;;;;;;;;;;;;;;;626:208;;8:9:-1;5:2;;;30:1;27;20:12;5:2;626:208:4;;;;;;;;;;;;;;;;;;;;;;;;;;;;;244:4:8;222:27;;:10;:27;;;214:36;;;;;;;;791:1:4;776:11;:16;;;;768:25;;;;;;;;816:11;803:10;;:24;;;;;;;;;;;;;;;;;;626:208;:::o",
"source": "pragma solidity 0.4.23;\nimport \"./SelfAuthorized.sol\";\n\n\n/// @title MasterCopy - Base for master copy contracts (should always be first super contract)\n/// @author Richard Meissner - <richard@gnosis.pm>\ncontract MasterCopy is SelfAuthorized {\n // masterCopy always needs to be first declared variable, to ensure that it is at the same location as in the Proxy contract.\n // It should also always be ensured that the address is stored alone (uses a full word)\n address masterCopy;\n\n /// @dev Allows to upgrade the contract. This can only be done via a Safe transaction.\n /// @param _masterCopy New contract address.\n function changeMasterCopy(address _masterCopy)\n public\n authorized\n {\n // Master copy address cannot be null.\n require(_masterCopy != 0);\n masterCopy = _masterCopy;\n }\n}\n",
"sourcePath": "/Users/apanizo/git/gnosis/safe-contracts/contracts/MasterCopy.sol",
"ast": {
"absolutePath": "/Users/apanizo/git/gnosis/safe-contracts/contracts/MasterCopy.sol",
"exportedSymbols": {
"MasterCopy": [
779
580
]
},
"id": 780,
"id": 581,
"nodeType": "SourceUnit",
"nodes": [
{
"id": 755,
"id": 556,
"literals": [
"solidity",
"0.4",
".23"
],
"nodeType": "PragmaDirective",
"src": "0:23:6"
"src": "0:23:4"
},
{
"absolutePath": "/Users/apanizo/git/gnosis/safe-contracts/contracts/SelfAuthorized.sol",
"file": "./SelfAuthorized.sol",
"id": 756,
"id": 557,
"nodeType": "ImportDirective",
"scope": 780,
"sourceUnit": 1560,
"src": "24:30:6",
"scope": 581,
"sourceUnit": 1360,
"src": "24:30:4",
"symbolAliases": [],
"unitAlias": ""
},
@ -59,42 +59,42 @@
"arguments": null,
"baseName": {
"contractScope": null,
"id": 757,
"id": 558,
"name": "SelfAuthorized",
"nodeType": "UserDefinedTypeName",
"referencedDeclaration": 1559,
"src": "226:14:6",
"referencedDeclaration": 1359,
"src": "226:14:4",
"typeDescriptions": {
"typeIdentifier": "t_contract$_SelfAuthorized_$1559",
"typeIdentifier": "t_contract$_SelfAuthorized_$1359",
"typeString": "contract SelfAuthorized"
}
},
"id": 758,
"id": 559,
"nodeType": "InheritanceSpecifier",
"src": "226:14:6"
"src": "226:14:4"
}
],
"contractDependencies": [
1559
1359
],
"contractKind": "contract",
"documentation": "@title MasterCopy - Base for master copy contracts (should always be first super contract)\n @author Richard Meissner - <richard@gnosis.pm>",
"fullyImplemented": true,
"id": 779,
"id": 580,
"linearizedBaseContracts": [
779,
1559
580,
1359
],
"name": "MasterCopy",
"nodeType": "ContractDefinition",
"nodes": [
{
"constant": false,
"id": 760,
"id": 561,
"name": "masterCopy",
"nodeType": "VariableDeclaration",
"scope": 779,
"src": "465:18:6",
"scope": 580,
"src": "465:18:4",
"stateVariable": true,
"storageLocation": "default",
"typeDescriptions": {
@ -102,10 +102,10 @@
"typeString": "address"
},
"typeName": {
"id": 759,
"id": 560,
"name": "address",
"nodeType": "ElementaryTypeName",
"src": "465:7:6",
"src": "465:7:4",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
@ -116,9 +116,9 @@
},
{
"body": {
"id": 777,
"id": 578,
"nodeType": "Block",
"src": "711:123:6",
"src": "711:123:4",
"statements": [
{
"expression": {
@ -130,19 +130,19 @@
"typeIdentifier": "t_address",
"typeString": "address"
},
"id": 770,
"id": 571,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftExpression": {
"argumentTypes": null,
"id": 768,
"id": 569,
"name": "_masterCopy",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 762,
"src": "776:11:6",
"referencedDeclaration": 563,
"src": "776:11:4",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
@ -153,14 +153,14 @@
"rightExpression": {
"argumentTypes": null,
"hexValue": "30",
"id": 769,
"id": 570,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "791:1:6",
"src": "791:1:4",
"subdenomination": null,
"typeDescriptions": {
"typeIdentifier": "t_rational_0_by_1",
@ -168,7 +168,7 @@
},
"value": "0"
},
"src": "776:16:6",
"src": "776:16:4",
"typeDescriptions": {
"typeIdentifier": "t_bool",
"typeString": "bool"
@ -182,21 +182,21 @@
"typeString": "bool"
}
],
"id": 767,
"id": 568,
"name": "require",
"nodeType": "Identifier",
"overloadedDeclarations": [
2468,
2469
2399,
2400
],
"referencedDeclaration": 2468,
"src": "768:7:6",
"referencedDeclaration": 2399,
"src": "768:7:4",
"typeDescriptions": {
"typeIdentifier": "t_function_require_pure$_t_bool_$returns$__$",
"typeString": "function (bool) pure"
}
},
"id": 771,
"id": 572,
"isConstant": false,
"isLValue": false,
"isPure": false,
@ -204,32 +204,32 @@
"lValueRequested": false,
"names": [],
"nodeType": "FunctionCall",
"src": "768:25:6",
"src": "768:25:4",
"typeDescriptions": {
"typeIdentifier": "t_tuple$__$",
"typeString": "tuple()"
}
},
"id": 772,
"id": 573,
"nodeType": "ExpressionStatement",
"src": "768:25:6"
"src": "768:25:4"
},
{
"expression": {
"argumentTypes": null,
"id": 775,
"id": 576,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftHandSide": {
"argumentTypes": null,
"id": 773,
"id": 574,
"name": "masterCopy",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 760,
"src": "803:10:6",
"referencedDeclaration": 561,
"src": "803:10:4",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
@ -239,68 +239,68 @@
"operator": "=",
"rightHandSide": {
"argumentTypes": null,
"id": 774,
"id": 575,
"name": "_masterCopy",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 762,
"src": "816:11:6",
"referencedDeclaration": 563,
"src": "816:11:4",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
}
},
"src": "803:24:6",
"src": "803:24:4",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
}
},
"id": 776,
"id": 577,
"nodeType": "ExpressionStatement",
"src": "803:24:6"
"src": "803:24:4"
}
]
},
"documentation": "@dev Allows to upgrade the contract. This can only be done via a Safe transaction.\n @param _masterCopy New contract address.",
"id": 778,
"id": 579,
"implemented": true,
"isConstructor": false,
"isDeclaredConst": false,
"modifiers": [
{
"arguments": null,
"id": 765,
"id": 566,
"modifierName": {
"argumentTypes": null,
"id": 764,
"id": 565,
"name": "authorized",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 1558,
"src": "696:10:6",
"referencedDeclaration": 1358,
"src": "696:10:4",
"typeDescriptions": {
"typeIdentifier": "t_modifier$__$",
"typeString": "modifier ()"
}
},
"nodeType": "ModifierInvocation",
"src": "696:10:6"
"src": "696:10:4"
}
],
"name": "changeMasterCopy",
"nodeType": "FunctionDefinition",
"parameters": {
"id": 763,
"id": 564,
"nodeType": "ParameterList",
"parameters": [
{
"constant": false,
"id": 762,
"id": 563,
"name": "_masterCopy",
"nodeType": "VariableDeclaration",
"scope": 778,
"src": "652:19:6",
"scope": 579,
"src": "652:19:4",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions": {
@ -308,10 +308,10 @@
"typeString": "address"
},
"typeName": {
"id": 761,
"id": 562,
"name": "address",
"nodeType": "ElementaryTypeName",
"src": "652:7:6",
"src": "652:7:4",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
@ -321,56 +321,56 @@
"visibility": "internal"
}
],
"src": "651:21:6"
"src": "651:21:4"
},
"payable": false,
"returnParameters": {
"id": 766,
"id": 567,
"nodeType": "ParameterList",
"parameters": [],
"src": "711:0:6"
"src": "711:0:4"
},
"scope": 779,
"src": "626:208:6",
"scope": 580,
"src": "626:208:4",
"stateMutability": "nonpayable",
"superFunction": null,
"visibility": "public"
}
],
"scope": 780,
"src": "203:633:6"
"scope": 581,
"src": "203:633:4"
}
],
"src": "0:837:6"
"src": "0:837:4"
},
"legacyAST": {
"absolutePath": "/Users/apanizo/git/gnosis/safe-contracts/contracts/MasterCopy.sol",
"exportedSymbols": {
"MasterCopy": [
779
580
]
},
"id": 780,
"id": 581,
"nodeType": "SourceUnit",
"nodes": [
{
"id": 755,
"id": 556,
"literals": [
"solidity",
"0.4",
".23"
],
"nodeType": "PragmaDirective",
"src": "0:23:6"
"src": "0:23:4"
},
{
"absolutePath": "/Users/apanizo/git/gnosis/safe-contracts/contracts/SelfAuthorized.sol",
"file": "./SelfAuthorized.sol",
"id": 756,
"id": 557,
"nodeType": "ImportDirective",
"scope": 780,
"sourceUnit": 1560,
"src": "24:30:6",
"scope": 581,
"sourceUnit": 1360,
"src": "24:30:4",
"symbolAliases": [],
"unitAlias": ""
},
@ -380,42 +380,42 @@
"arguments": null,
"baseName": {
"contractScope": null,
"id": 757,
"id": 558,
"name": "SelfAuthorized",
"nodeType": "UserDefinedTypeName",
"referencedDeclaration": 1559,
"src": "226:14:6",
"referencedDeclaration": 1359,
"src": "226:14:4",
"typeDescriptions": {
"typeIdentifier": "t_contract$_SelfAuthorized_$1559",
"typeIdentifier": "t_contract$_SelfAuthorized_$1359",
"typeString": "contract SelfAuthorized"
}
},
"id": 758,
"id": 559,
"nodeType": "InheritanceSpecifier",
"src": "226:14:6"
"src": "226:14:4"
}
],
"contractDependencies": [
1559
1359
],
"contractKind": "contract",
"documentation": "@title MasterCopy - Base for master copy contracts (should always be first super contract)\n @author Richard Meissner - <richard@gnosis.pm>",
"fullyImplemented": true,
"id": 779,
"id": 580,
"linearizedBaseContracts": [
779,
1559
580,
1359
],
"name": "MasterCopy",
"nodeType": "ContractDefinition",
"nodes": [
{
"constant": false,
"id": 760,
"id": 561,
"name": "masterCopy",
"nodeType": "VariableDeclaration",
"scope": 779,
"src": "465:18:6",
"scope": 580,
"src": "465:18:4",
"stateVariable": true,
"storageLocation": "default",
"typeDescriptions": {
@ -423,10 +423,10 @@
"typeString": "address"
},
"typeName": {
"id": 759,
"id": 560,
"name": "address",
"nodeType": "ElementaryTypeName",
"src": "465:7:6",
"src": "465:7:4",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
@ -437,9 +437,9 @@
},
{
"body": {
"id": 777,
"id": 578,
"nodeType": "Block",
"src": "711:123:6",
"src": "711:123:4",
"statements": [
{
"expression": {
@ -451,19 +451,19 @@
"typeIdentifier": "t_address",
"typeString": "address"
},
"id": 770,
"id": 571,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftExpression": {
"argumentTypes": null,
"id": 768,
"id": 569,
"name": "_masterCopy",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 762,
"src": "776:11:6",
"referencedDeclaration": 563,
"src": "776:11:4",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
@ -474,14 +474,14 @@
"rightExpression": {
"argumentTypes": null,
"hexValue": "30",
"id": 769,
"id": 570,
"isConstant": false,
"isLValue": false,
"isPure": true,
"kind": "number",
"lValueRequested": false,
"nodeType": "Literal",
"src": "791:1:6",
"src": "791:1:4",
"subdenomination": null,
"typeDescriptions": {
"typeIdentifier": "t_rational_0_by_1",
@ -489,7 +489,7 @@
},
"value": "0"
},
"src": "776:16:6",
"src": "776:16:4",
"typeDescriptions": {
"typeIdentifier": "t_bool",
"typeString": "bool"
@ -503,21 +503,21 @@
"typeString": "bool"
}
],
"id": 767,
"id": 568,
"name": "require",
"nodeType": "Identifier",
"overloadedDeclarations": [
2468,
2469
2399,
2400
],
"referencedDeclaration": 2468,
"src": "768:7:6",
"referencedDeclaration": 2399,
"src": "768:7:4",
"typeDescriptions": {
"typeIdentifier": "t_function_require_pure$_t_bool_$returns$__$",
"typeString": "function (bool) pure"
}
},
"id": 771,
"id": 572,
"isConstant": false,
"isLValue": false,
"isPure": false,
@ -525,32 +525,32 @@
"lValueRequested": false,
"names": [],
"nodeType": "FunctionCall",
"src": "768:25:6",
"src": "768:25:4",
"typeDescriptions": {
"typeIdentifier": "t_tuple$__$",
"typeString": "tuple()"
}
},
"id": 772,
"id": 573,
"nodeType": "ExpressionStatement",
"src": "768:25:6"
"src": "768:25:4"
},
{
"expression": {
"argumentTypes": null,
"id": 775,
"id": 576,
"isConstant": false,
"isLValue": false,
"isPure": false,
"lValueRequested": false,
"leftHandSide": {
"argumentTypes": null,
"id": 773,
"id": 574,
"name": "masterCopy",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 760,
"src": "803:10:6",
"referencedDeclaration": 561,
"src": "803:10:4",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
@ -560,68 +560,68 @@
"operator": "=",
"rightHandSide": {
"argumentTypes": null,
"id": 774,
"id": 575,
"name": "_masterCopy",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 762,
"src": "816:11:6",
"referencedDeclaration": 563,
"src": "816:11:4",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
}
},
"src": "803:24:6",
"src": "803:24:4",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
}
},
"id": 776,
"id": 577,
"nodeType": "ExpressionStatement",
"src": "803:24:6"
"src": "803:24:4"
}
]
},
"documentation": "@dev Allows to upgrade the contract. This can only be done via a Safe transaction.\n @param _masterCopy New contract address.",
"id": 778,
"id": 579,
"implemented": true,
"isConstructor": false,
"isDeclaredConst": false,
"modifiers": [
{
"arguments": null,
"id": 765,
"id": 566,
"modifierName": {
"argumentTypes": null,
"id": 764,
"id": 565,
"name": "authorized",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 1558,
"src": "696:10:6",
"referencedDeclaration": 1358,
"src": "696:10:4",
"typeDescriptions": {
"typeIdentifier": "t_modifier$__$",
"typeString": "modifier ()"
}
},
"nodeType": "ModifierInvocation",
"src": "696:10:6"
"src": "696:10:4"
}
],
"name": "changeMasterCopy",
"nodeType": "FunctionDefinition",
"parameters": {
"id": 763,
"id": 564,
"nodeType": "ParameterList",
"parameters": [
{
"constant": false,
"id": 762,
"id": 563,
"name": "_masterCopy",
"nodeType": "VariableDeclaration",
"scope": 778,
"src": "652:19:6",
"scope": 579,
"src": "652:19:4",
"stateVariable": false,
"storageLocation": "default",
"typeDescriptions": {
@ -629,10 +629,10 @@
"typeString": "address"
},
"typeName": {
"id": 761,
"id": 562,
"name": "address",
"nodeType": "ElementaryTypeName",
"src": "652:7:6",
"src": "652:7:4",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
@ -642,27 +642,27 @@
"visibility": "internal"
}
],
"src": "651:21:6"
"src": "651:21:4"
},
"payable": false,
"returnParameters": {
"id": 766,
"id": 567,
"nodeType": "ParameterList",
"parameters": [],
"src": "711:0:6"
"src": "711:0:4"
},
"scope": 779,
"src": "626:208:6",
"scope": 580,
"src": "626:208:4",
"stateMutability": "nonpayable",
"superFunction": null,
"visibility": "public"
}
],
"scope": 780,
"src": "203:633:6"
"scope": 581,
"src": "203:633:4"
}
],
"src": "0:837:6"
"src": "0:837:4"
},
"compiler": {
"name": "solc",
@ -670,5 +670,5 @@
},
"networks": {},
"schemaVersion": "2.0.0",
"updatedAt": "2018-05-10T10:43:07.897Z"
"updatedAt": "2018-05-16T10:51:14.746Z"
}

View File

@ -1378,8 +1378,8 @@
"4": {
"events": {},
"links": {},
"address": "0xcf171a1fe7e24ac529ec0436cd51543469488a30",
"transactionHash": "0x52b1aad2d523bc57e2729516009b2dc46c58b5287c72ca9fa2faf949ad3ed32a"
"address": "0x682586e353e6befc8c7c09ba28165afca941ed5f",
"transactionHash": "0xfa828695bce76ea64bfa11fac92c01894ca684341a49e1d583c43a0d13bb0ec1"
},
"42": {
"events": {},
@ -1398,8 +1398,14 @@
"links": {},
"address": "0x3b293b12ee278dba3d4350cd5b4434c228bad69b",
"transactionHash": "0x137111f15934455430bea53bd8a6721561285af6a431f174f090257877635ab6"
},
"1526478212260": {
"events": {},
"links": {},
"address": "0x6ff07ab4d4ecb8339dee6bd028e379c2a1992103",
"transactionHash": "0x137111f15934455430bea53bd8a6721561285af6a431f174f090257877635ab6"
}
},
"schemaVersion": "2.0.0",
"updatedAt": "2018-05-14T07:39:37.978Z"
"updatedAt": "2018-05-16T13:45:24.532Z"
}

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -340,8 +340,8 @@
"4": {
"events": {},
"links": {},
"address": "0x0bcf053aec288e75a338486b27d1340b11a5a818",
"transactionHash": "0x670d0ace2ffca0389ecff0dd2fb54fee15d237e652e7e67a06586187d00e3f2a"
"address": "0xeb51df3ce4e31ee60ed86cc860e68a4f892960cc",
"transactionHash": "0x1a3baba678d7b4d4c2ae5d151176442d5306e7958e83cecf49a6256fdfd2f4cb"
},
"1525950336085": {
"events": {},
@ -354,8 +354,14 @@
"links": {},
"address": "0xf5cfa4069271285402ba2585c521c6c627810963",
"transactionHash": "0xf4586ae05ae02801de1759128e43658bb0439e622a5ba84ad6bb4b652d641f4f"
},
"1526478212260": {
"events": {},
"links": {},
"address": "0x20658014abeebf3f064bf4442a5cd160143b800e",
"transactionHash": "0xf4586ae05ae02801de1759128e43658bb0439e622a5ba84ad6bb4b652d641f4f"
}
},
"schemaVersion": "2.0.0",
"updatedAt": "2018-05-14T07:39:37.970Z"
"updatedAt": "2018-05-16T13:45:24.531Z"
}

File diff suppressed because one or more lines are too long

View File

@ -991,8 +991,8 @@
"4": {
"events": {},
"links": {},
"address": "0xdc7a0c8475e99fa755e935ffbe04b84ead9aadc7",
"transactionHash": "0xd1d3b32e56f0533181f582cabad03ce3e98dd1083b31baff076d9e53d1143e15"
"address": "0xf11c9ac85e73435180707156748ecbaf4efc035b",
"transactionHash": "0xf8c48bc1ea023ab15194af47f50d2c8eaeb3d7b9dd13e7325e892e92743c2979"
},
"1525950336085": {
"events": {},
@ -1005,8 +1005,14 @@
"links": {},
"address": "0x321151783f8dfb4699370d1bd5cee4e82bc3b52a",
"transactionHash": "0x5b47c779cfd719a97f218a56d99b64b2c5b382549f3375822d5afed010cdb9c5"
},
"1526478212260": {
"events": {},
"links": {},
"address": "0xf7f9b14921d4723eae3a8b29784c100301f6d8b8",
"transactionHash": "0x5b47c779cfd719a97f218a56d99b64b2c5b382549f3375822d5afed010cdb9c5"
}
},
"schemaVersion": "2.0.0",
"updatedAt": "2018-05-14T07:39:37.950Z"
"updatedAt": "2018-05-16T13:45:24.507Z"
}

View File

@ -3,29 +3,29 @@
"abi": [],
"bytecode": "0x6080604052348015600f57600080fd5b50603580601d6000396000f3006080604052600080fd00a165627a7a72305820c359a8a0df732b4d3e100e43277411dee19c572529edb454cbf1fa9ee91508150029",
"deployedBytecode": "0x6080604052600080fd00a165627a7a72305820c359a8a0df732b4d3e100e43277411dee19c572529edb454cbf1fa9ee91508150029",
"sourceMap": "152:118:14:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;152:118:14;;;;;;;",
"deployedSourceMap": "152:118:14:-;;;;;",
"sourceMap": "152:118:8:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;152:118:8;;;;;;;",
"deployedSourceMap": "152:118:8:-;;;;;",
"source": "pragma solidity 0.4.23;\n\n\n/// @title SelfAuthorized - authorizes current contract to perform actions\n/// @author Richard Meissner - <richard@gnosis.pm>\ncontract SelfAuthorized {\n modifier authorized() {\n require(msg.sender == address(this));\n _;\n }\n}\n",
"sourcePath": "/Users/apanizo/git/gnosis/safe-contracts/contracts/SelfAuthorized.sol",
"ast": {
"absolutePath": "/Users/apanizo/git/gnosis/safe-contracts/contracts/SelfAuthorized.sol",
"exportedSymbols": {
"SelfAuthorized": [
1559
1359
]
},
"id": 1560,
"id": 1360,
"nodeType": "SourceUnit",
"nodes": [
{
"id": 1545,
"id": 1345,
"literals": [
"solidity",
"0.4",
".23"
],
"nodeType": "PragmaDirective",
"src": "0:23:14"
"src": "0:23:8"
},
{
"baseContracts": [],
@ -33,18 +33,18 @@
"contractKind": "contract",
"documentation": "@title SelfAuthorized - authorizes current contract to perform actions\n @author Richard Meissner - <richard@gnosis.pm>",
"fullyImplemented": true,
"id": 1559,
"id": 1359,
"linearizedBaseContracts": [
1559
1359
],
"name": "SelfAuthorized",
"nodeType": "ContractDefinition",
"nodes": [
{
"body": {
"id": 1557,
"id": 1357,
"nodeType": "Block",
"src": "204:64:14",
"src": "204:64:8",
"statements": [
{
"expression": {
@ -56,7 +56,7 @@
"typeIdentifier": "t_address",
"typeString": "address"
},
"id": 1553,
"id": 1353,
"isConstant": false,
"isLValue": false,
"isPure": false,
@ -65,18 +65,18 @@
"argumentTypes": null,
"expression": {
"argumentTypes": null,
"id": 1548,
"id": 1348,
"name": "msg",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 2465,
"src": "222:3:14",
"referencedDeclaration": 2396,
"src": "222:3:8",
"typeDescriptions": {
"typeIdentifier": "t_magic_message",
"typeString": "msg"
}
},
"id": 1549,
"id": 1349,
"isConstant": false,
"isLValue": false,
"isPure": false,
@ -84,7 +84,7 @@
"memberName": "sender",
"nodeType": "MemberAccess",
"referencedDeclaration": null,
"src": "222:10:14",
"src": "222:10:8",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
@ -97,14 +97,14 @@
"arguments": [
{
"argumentTypes": null,
"id": 1551,
"id": 1351,
"name": "this",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 2484,
"src": "244:4:14",
"referencedDeclaration": 2411,
"src": "244:4:8",
"typeDescriptions": {
"typeIdentifier": "t_contract$_SelfAuthorized_$1559",
"typeIdentifier": "t_contract$_SelfAuthorized_$1359",
"typeString": "contract SelfAuthorized"
}
}
@ -112,24 +112,24 @@
"expression": {
"argumentTypes": [
{
"typeIdentifier": "t_contract$_SelfAuthorized_$1559",
"typeIdentifier": "t_contract$_SelfAuthorized_$1359",
"typeString": "contract SelfAuthorized"
}
],
"id": 1550,
"id": 1350,
"isConstant": false,
"isLValue": false,
"isPure": true,
"lValueRequested": false,
"nodeType": "ElementaryTypeNameExpression",
"src": "236:7:14",
"src": "236:7:8",
"typeDescriptions": {
"typeIdentifier": "t_type$_t_address_$",
"typeString": "type(address)"
},
"typeName": "address"
},
"id": 1552,
"id": 1352,
"isConstant": false,
"isLValue": false,
"isPure": false,
@ -137,13 +137,13 @@
"lValueRequested": false,
"names": [],
"nodeType": "FunctionCall",
"src": "236:13:14",
"src": "236:13:8",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
}
},
"src": "222:27:14",
"src": "222:27:8",
"typeDescriptions": {
"typeIdentifier": "t_bool",
"typeString": "bool"
@ -157,21 +157,21 @@
"typeString": "bool"
}
],
"id": 1547,
"id": 1347,
"name": "require",
"nodeType": "Identifier",
"overloadedDeclarations": [
2468,
2469
2399,
2400
],
"referencedDeclaration": 2468,
"src": "214:7:14",
"referencedDeclaration": 2399,
"src": "214:7:8",
"typeDescriptions": {
"typeIdentifier": "t_function_require_pure$_t_bool_$returns$__$",
"typeString": "function (bool) pure"
}
},
"id": 1554,
"id": 1354,
"isConstant": false,
"isLValue": false,
"isPure": false,
@ -179,62 +179,62 @@
"lValueRequested": false,
"names": [],
"nodeType": "FunctionCall",
"src": "214:36:14",
"src": "214:36:8",
"typeDescriptions": {
"typeIdentifier": "t_tuple$__$",
"typeString": "tuple()"
}
},
"id": 1555,
"id": 1355,
"nodeType": "ExpressionStatement",
"src": "214:36:14"
"src": "214:36:8"
},
{
"id": 1556,
"id": 1356,
"nodeType": "PlaceholderStatement",
"src": "260:1:14"
"src": "260:1:8"
}
]
},
"documentation": null,
"id": 1558,
"id": 1358,
"name": "authorized",
"nodeType": "ModifierDefinition",
"parameters": {
"id": 1546,
"id": 1346,
"nodeType": "ParameterList",
"parameters": [],
"src": "201:2:14"
"src": "201:2:8"
},
"src": "182:86:14",
"src": "182:86:8",
"visibility": "internal"
}
],
"scope": 1560,
"src": "152:118:14"
"scope": 1360,
"src": "152:118:8"
}
],
"src": "0:271:14"
"src": "0:271:8"
},
"legacyAST": {
"absolutePath": "/Users/apanizo/git/gnosis/safe-contracts/contracts/SelfAuthorized.sol",
"exportedSymbols": {
"SelfAuthorized": [
1559
1359
]
},
"id": 1560,
"id": 1360,
"nodeType": "SourceUnit",
"nodes": [
{
"id": 1545,
"id": 1345,
"literals": [
"solidity",
"0.4",
".23"
],
"nodeType": "PragmaDirective",
"src": "0:23:14"
"src": "0:23:8"
},
{
"baseContracts": [],
@ -242,18 +242,18 @@
"contractKind": "contract",
"documentation": "@title SelfAuthorized - authorizes current contract to perform actions\n @author Richard Meissner - <richard@gnosis.pm>",
"fullyImplemented": true,
"id": 1559,
"id": 1359,
"linearizedBaseContracts": [
1559
1359
],
"name": "SelfAuthorized",
"nodeType": "ContractDefinition",
"nodes": [
{
"body": {
"id": 1557,
"id": 1357,
"nodeType": "Block",
"src": "204:64:14",
"src": "204:64:8",
"statements": [
{
"expression": {
@ -265,7 +265,7 @@
"typeIdentifier": "t_address",
"typeString": "address"
},
"id": 1553,
"id": 1353,
"isConstant": false,
"isLValue": false,
"isPure": false,
@ -274,18 +274,18 @@
"argumentTypes": null,
"expression": {
"argumentTypes": null,
"id": 1548,
"id": 1348,
"name": "msg",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 2465,
"src": "222:3:14",
"referencedDeclaration": 2396,
"src": "222:3:8",
"typeDescriptions": {
"typeIdentifier": "t_magic_message",
"typeString": "msg"
}
},
"id": 1549,
"id": 1349,
"isConstant": false,
"isLValue": false,
"isPure": false,
@ -293,7 +293,7 @@
"memberName": "sender",
"nodeType": "MemberAccess",
"referencedDeclaration": null,
"src": "222:10:14",
"src": "222:10:8",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
@ -306,14 +306,14 @@
"arguments": [
{
"argumentTypes": null,
"id": 1551,
"id": 1351,
"name": "this",
"nodeType": "Identifier",
"overloadedDeclarations": [],
"referencedDeclaration": 2484,
"src": "244:4:14",
"referencedDeclaration": 2411,
"src": "244:4:8",
"typeDescriptions": {
"typeIdentifier": "t_contract$_SelfAuthorized_$1559",
"typeIdentifier": "t_contract$_SelfAuthorized_$1359",
"typeString": "contract SelfAuthorized"
}
}
@ -321,24 +321,24 @@
"expression": {
"argumentTypes": [
{
"typeIdentifier": "t_contract$_SelfAuthorized_$1559",
"typeIdentifier": "t_contract$_SelfAuthorized_$1359",
"typeString": "contract SelfAuthorized"
}
],
"id": 1550,
"id": 1350,
"isConstant": false,
"isLValue": false,
"isPure": true,
"lValueRequested": false,
"nodeType": "ElementaryTypeNameExpression",
"src": "236:7:14",
"src": "236:7:8",
"typeDescriptions": {
"typeIdentifier": "t_type$_t_address_$",
"typeString": "type(address)"
},
"typeName": "address"
},
"id": 1552,
"id": 1352,
"isConstant": false,
"isLValue": false,
"isPure": false,
@ -346,13 +346,13 @@
"lValueRequested": false,
"names": [],
"nodeType": "FunctionCall",
"src": "236:13:14",
"src": "236:13:8",
"typeDescriptions": {
"typeIdentifier": "t_address",
"typeString": "address"
}
},
"src": "222:27:14",
"src": "222:27:8",
"typeDescriptions": {
"typeIdentifier": "t_bool",
"typeString": "bool"
@ -366,21 +366,21 @@
"typeString": "bool"
}
],
"id": 1547,
"id": 1347,
"name": "require",
"nodeType": "Identifier",
"overloadedDeclarations": [
2468,
2469
2399,
2400
],
"referencedDeclaration": 2468,
"src": "214:7:14",
"referencedDeclaration": 2399,
"src": "214:7:8",
"typeDescriptions": {
"typeIdentifier": "t_function_require_pure$_t_bool_$returns$__$",
"typeString": "function (bool) pure"
}
},
"id": 1554,
"id": 1354,
"isConstant": false,
"isLValue": false,
"isPure": false,
@ -388,42 +388,42 @@
"lValueRequested": false,
"names": [],
"nodeType": "FunctionCall",
"src": "214:36:14",
"src": "214:36:8",
"typeDescriptions": {
"typeIdentifier": "t_tuple$__$",
"typeString": "tuple()"
}
},
"id": 1555,
"id": 1355,
"nodeType": "ExpressionStatement",
"src": "214:36:14"
"src": "214:36:8"
},
{
"id": 1556,
"id": 1356,
"nodeType": "PlaceholderStatement",
"src": "260:1:14"
"src": "260:1:8"
}
]
},
"documentation": null,
"id": 1558,
"id": 1358,
"name": "authorized",
"nodeType": "ModifierDefinition",
"parameters": {
"id": 1546,
"id": 1346,
"nodeType": "ParameterList",
"parameters": [],
"src": "201:2:14"
"src": "201:2:8"
},
"src": "182:86:14",
"src": "182:86:8",
"visibility": "internal"
}
],
"scope": 1560,
"src": "152:118:14"
"scope": 1360,
"src": "152:118:8"
}
],
"src": "0:271:14"
"src": "0:271:8"
},
"compiler": {
"name": "solc",
@ -431,5 +431,5 @@
},
"networks": {},
"schemaVersion": "2.0.0",
"updatedAt": "2018-05-10T10:43:07.901Z"
"updatedAt": "2018-05-16T10:51:14.750Z"
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,34 +1,6 @@
// @flow
import * as React from 'react'
import Button from '~/components/layout/Button'
import Link from '~/components/layout/Link'
type NextButtonProps = {
text: string,
disabled: boolean,
}
const NextButton = ({ text, disabled }: NextButtonProps) => (
<Button
variant="raised"
color="primary"
type="submit"
disabled={disabled}
>
{text}
</Button>
)
type GoProps = {
title: string,
to: string,
}
const GoButton = ({ title, to }: GoProps) => (
<Link to={to}>
<NextButton text={title} disabled={false} />
</Link>
)
type ControlProps = {
next: string,
@ -48,34 +20,37 @@ const ControlButtons = ({
>
Back
</Button>
<NextButton text={next} disabled={submitting} />
<Button
variant="raised"
color="primary"
type="submit"
disabled={submitting}
>
{next}
</Button>
</React.Fragment>
)
type Props = {
finishedTx: boolean,
finishedButton: React$Node,
onPrevious: () => void,
firstPage: boolean,
lastPage: boolean,
submitting: boolean,
goTitle: string,
goPath: string,
}
const Controls = ({
finishedTx, onPrevious, firstPage, lastPage, submitting, goTitle, goPath,
finishedTx, finishedButton, onPrevious, firstPage, lastPage, submitting,
}: Props) => (
<React.Fragment>
{ finishedTx
? <GoButton title={goTitle} to={goPath} />
: <ControlButtons
submitting={submitting}
next={lastPage ? 'Finish' : 'Next'}
firstPage={firstPage}
onPrevious={onPrevious}
/>
}
</React.Fragment>
finishedTx
? <React.Fragment>{finishedButton}</React.Fragment>
: <ControlButtons
submitting={submitting}
next={lastPage ? 'Finish' : 'Next'}
firstPage={firstPage}
onPrevious={onPrevious}
/>
)
export default Controls

View File

@ -4,6 +4,7 @@ import { withStyles } from 'material-ui/styles'
import * as React from 'react'
import type { FormApi } from 'react-final-form'
import GnoForm from '~/components/forms/GnoForm'
import Button from '~/components/layout/Button'
import Col from '~/components/layout/Col'
import Row from '~/components/layout/Row'
import Controls from './Controls'
@ -12,12 +13,12 @@ export { default as Step } from './Step'
type Props = {
classes: Object,
goTitle: string,
goPath: string,
steps: string[],
finishedTransaction: boolean,
finishedButton: React$Node,
initialValues?: Object,
children: React$Node,
onReset?: () => void,
onSubmit: (values: Object, form: FormApi, callback: ?(errors: ?Object) => void) => ?Object | Promise<?Object> | void,
}
@ -33,6 +34,13 @@ type PageProps = {
class GnoStepper extends React.PureComponent<Props, State> {
static Page = ({ children }: PageProps) => children
static FinishButton = ({
component, to, title, ...props
}) => (
<Button component={component} to={to} variant="raised" color="primary" {...props}>
{title}
</Button>
)
constructor(props: Props) {
super(props)
@ -42,6 +50,17 @@ class GnoStepper extends React.PureComponent<Props, State> {
}
}
onReset = () => {
const resetCallback = this.props.onReset
if (resetCallback) {
resetCallback()
}
this.setState(() => ({
page: 0,
values: this.props.initialValues || {},
}))
}
getActivePageFrom = (pages: React$Node) => {
const activePageProps = React.Children.toArray(pages)[this.state.page].props
const { children, ...props } = activePageProps
@ -80,11 +99,12 @@ class GnoStepper extends React.PureComponent<Props, State> {
render() {
const {
steps, children, finishedTransaction, goTitle, goPath, classes,
steps, children, finishedTransaction, finishedButton, classes,
} = this.props
const { page, values } = this.state
const activePage = this.getActivePageFrom(children)
const isLastPage = page === steps.length - 1
const finished = React.cloneElement(React.Children.only(finishedButton), { onClick: this.onReset })
return (
<React.Fragment>
@ -108,11 +128,10 @@ class GnoStepper extends React.PureComponent<Props, State> {
<Controls
submitting={submitting}
finishedTx={finishedTransaction}
finishedButton={finished}
onPrevious={this.previous}
firstPage={page === 0}
lastPage={isLastPage}
goTitle={goTitle}
goPath={goPath}
/>
</Col>
</Row>

View File

@ -6,6 +6,7 @@ import Confirmation from '~/routes/open/components/FormConfirmation'
import Review from '~/routes/open/components/ReviewInformation'
import SafeFields, { safeFieldsValidation } from '~/routes/open/components/SafeForm'
import { SAFELIST_ADDRESS } from '~/routes/routes'
import Link from '~/components/layout/Link'
const getSteps = () => [
'Fill Safe Form', 'Review Information', 'Deploy it',
@ -29,16 +30,16 @@ const Layout = ({
}: Props) => {
const steps = getSteps()
const initialValues = initialValuesFrom(userAccount)
const finishedButton = <Stepper.FinishButton title="VISIT SAFES" component={Link} to={SAFELIST_ADDRESS} />
return (
<React.Fragment>
{ provider
? (
<Stepper
goPath={SAFELIST_ADDRESS}
goTitle="VISIT SAFES"
onSubmit={onCallSafeContractSubmit}
finishedButton={finishedButton}
finishedTransaction={!!safeAddress}
onSubmit={onCallSafeContractSubmit}
steps={steps}
initialValues={initialValues}
>

View File

@ -15,6 +15,7 @@ import WithdrawnComponent, { SEE_TXS_BUTTON_TEXT } from '~/routes/safe/component
import { getBalanceInEtherOf } from '~/wallets/getWeb3'
import { sleep } from '~/utils/timer'
import { getDailyLimitFrom } from '~/routes/safe/component/Withdrawn/withdrawn'
import { type DailyLimitProps } from '~/routes/safe/store/model/dailyLimit'
describe('React DOM TESTS > Withdrawn funds from safe', () => {
let SafeDom

View File

@ -5,6 +5,7 @@ import Avatar from 'material-ui/Avatar'
import NotificationsPaused from 'material-ui-icons/NotificationsPaused'
import Button from '~/components/layout/Button'
import ListItemText from '~/components/List/ListItemText'
import { type DailyLimit } from '~/routes/safe/store/model/dailyLimit'
type Props = {
dailyLimit: DailyLimit,

View File

@ -1,9 +1,9 @@
// @flow
import { storiesOf } from '@storybook/react'
import * as React from 'react'
import Stepper from '~/components/Stepper'
import styles from '~/components/layout/PageFrame/index.scss'
import { makeDailyLimit, type DailyLimit } from '~/routes/safe/store/model/dailyLimit'
import Component from './index'
import WithdrawnForm from './index'
const FrameDecorator = story => (
@ -14,10 +14,8 @@ const FrameDecorator = story => (
storiesOf('Components', module)
.addDecorator(FrameDecorator)
.add('WitdrawnForm', () => {
const dailyLimit: DailyLimit = makeDailyLimit({ value: 10, spentToday: 6 })
return (
<Component dailyLimit={dailyLimit} safeAddress="" />
)
})
.add('WitdrawnForm', () => (
<Stepper.Page>
{ WithdrawnForm }
</Stepper.Page>
))

View File

@ -34,7 +34,7 @@ export const inLimit = (limit: number, spentToday: number) => (value: string) =>
return `Should not exceed ${max} ETH (amount to reach daily limit)`
}
export default ({ limit, spentToday }: Props) => () => (
const WithdrawnForm = ({ limit, spentToday }: Props) => () => (
<Block margin="md">
<Heading tag="h2" margin="lg">
Withdrawn Funds
@ -65,3 +65,4 @@ export default ({ limit, spentToday }: Props) => () => (
</Block>
)
export default WithdrawnForm

View File

@ -2,8 +2,8 @@
import * as React from 'react'
import { connect } from 'react-redux'
import Stepper from '~/components/Stepper'
import { SAFELIST_ADDRESS } from '~/routes/routes'
import { sleep } from '~/utils/timer'
import { type DailyLimit } from '~/routes/safe/store/model/dailyLimit'
import actions, { type Actions } from './actions'
import selector, { type SelectorProps } from './selector'
import withdrawn from './withdrawn'
@ -23,7 +23,7 @@ type State = {
done: boolean,
}
export const SEE_TXS_BUTTON_TEXT = 'DONE'
export const SEE_TXS_BUTTON_TEXT = 'RESET'
class Withdrawn extends React.Component<Props, State> {
state = {
@ -44,19 +44,24 @@ class Withdrawn extends React.Component<Props, State> {
}
}
onReset = () => {
this.setState({ done: false })
}
render() {
const { dailyLimit, safeAddress } = this.props
const { dailyLimit } = this.props
const { done } = this.state
const steps = getSteps()
const finishedButton = <Stepper.FinishButton title={SEE_TXS_BUTTON_TEXT} />
return (
<React.Fragment>
<Stepper
goPath={`${SAFELIST_ADDRESS}/${safeAddress}`}
goTitle={SEE_TXS_BUTTON_TEXT}
onSubmit={this.onWithdrawn}
finishedTransaction={done}
finishedButton={finishedButton}
onSubmit={this.onWithdrawn}
steps={steps}
onReset={this.onReset}
>
<Stepper.Page limit={dailyLimit.get('value')} spentToday={dailyLimit.get('spentToday')}>
{ WithdrawnForm }

View File

@ -1,7 +1,7 @@
// @flow
import { getWeb3 } from '~/wallets/getWeb3'
import { getGnosisSafeContract, getCreateDailyLimitExtensionContract } from '~/wallets/safeContracts'
import { type DailyLimitProps } from '~/routes/safe/store/model/safe'
import { type DailyLimitProps } from '~/routes/safe/store/model/dailyLimit'
export const LIMIT_POSITION = 0
export const SPENT_TODAY_POS = 1
@ -23,7 +23,7 @@ const getDailyLimitModuleFrom = async (safeAddress) => {
return dailyLimitModule
}
export const getDailyLimitFrom = async (safeAddress, tokenAddress): DailyLimitProps => {
export const getDailyLimitFrom = async (safeAddress: string, tokenAddress: number): Promise<DailyLimitProps> => {
const web3 = getWeb3()
const dailyLimitModule = await getDailyLimitModuleFrom(safeAddress)

View File

@ -18,7 +18,10 @@ class SafeView extends React.PureComponent<Props> {
fetchBalance(safeAddress)
}, 1500)
this.props.fetchDailyLimit(this.props.safe.get('address'))
const { fetchDailyLimit, safe } = this.props
if (safe) {
fetchDailyLimit(safe.get('address'))
}
}
componentWillUnmount() {

View File

@ -2,6 +2,7 @@
import type { Dispatch as ReduxDispatch } from 'redux'
import { type GlobalState } from '~/store/index'
import { getDailyLimitFrom } from '~/routes/safe/component/Withdrawn/withdrawn'
import { type DailyLimitProps } from '~/routes/safe/store/model/dailyLimit'
import updateDailyLimit from './updateDailyLimit'
export default (safeAddress: string) => async (dispatch: ReduxDispatch<GlobalState>) => {

View File

@ -1,5 +1,6 @@
// @flow
import { createAction } from 'redux-actions'
import { type DailyLimitProps } from '~/routes/safe/store/model/dailyLimit'
export const UPDATE_DAILY_LIMIT = 'UPDATE_DAILY_LIMIT'

View File

@ -25,7 +25,7 @@ const balanceReducerTests = () => {
expect(balances.get(address)).toBe('0')
})
it('reducer should return 1.3456 ETH as funds to safe with 1 ETH', async () => {
it('reducer should return 1.3456 ETH as funds to safe with 1.3456 ETH', async () => {
// GIVEN
const address = await aDeployedSafe(store)

View File

@ -44,21 +44,21 @@ class SafeBuilder {
const aSafe = () => new SafeBuilder()
export class SafeFactory {
static oneOwnerSafe = aSafe()
static oneOwnerSafe = (ownerAddress: string = '0x03db1a8b26d08df23337e9276a36b474510f0023') => aSafe()
.withAddress('0x03db1a8b26d08df23337e9276a36b474510f0025')
.withName('Adol ICO Safe')
.withConfirmations(1)
.withDailyLimit(10)
.withOwner(['Adol Metamask'], ['0x03db1a8b26d08df23337e9276a36b474510f0023'])
.withOwner(['Adol Metamask'], [ownerAddress])
.get()
static twoOwnersSafe = aSafe()
static twoOwnersSafe = (firstOwner: string = '0x03db1a8b26d08df23337e9276a36b474510f0023', secondOwner: string = '0x03db1a8b26d08df23337e9276a36b474510f0024') => aSafe()
.withAddress('0x03db1a8b26d08df23337e9276a36b474510f0026')
.withName('Adol & Tobias Safe')
.withConfirmations(2)
.withOwner(
['Adol Metamask', 'Tobias Metamask'],
['0x03db1a8b26d08df23337e9276a36b474510f0023', '0x03db1a8b26d08df23337e9276a36b474510f0024'],
[firstOwner, secondOwner],
)
.withDailyLimit(10, 1.34)
.get()

View File

@ -54,7 +54,7 @@ const providerReducerTests = () => {
const safes = store.getState()[SAFE_REDUCER_ID]
// THEN
expect(safes.get(address)).toEqual(SafeFactory.oneOwnerSafe)
expect(safes.get(address)).toEqual(SafeFactory.oneOwnerSafe())
})
it('reducer loads information from localStorage', async () => {

View File

@ -28,8 +28,8 @@ const safeSelectorTests = () => {
it('should return a list of size 2 when 2 safes are created', () => {
// GIVEN
let map: Map<string, Safe> = Map()
map = map.set('fooAddress', SafeFactory.oneOwnerSafe)
map = map.set('barAddress', SafeFactory.twoOwnersSafe)
map = map.set('fooAddress', SafeFactory.oneOwnerSafe())
map = map.set('barAddress', SafeFactory.twoOwnersSafe())
const match: Match = buildMathPropsFrom('fooAddress')
const undefMatch: Match = buildMathPropsFrom('inventedAddress')
@ -45,7 +45,7 @@ const safeSelectorTests = () => {
const undefinedSafe = safeSelector(reduxStore, { match: undefMatch })
// THEN
expect(oneOwnerSafe).toEqual(SafeFactory.oneOwnerSafe)
expect(oneOwnerSafe).toEqual(SafeFactory.oneOwnerSafe())
expect(undefinedSafe).toBe(undefined)
})
})

View File

@ -22,7 +22,7 @@ storiesOf('Routes /safes', module)
<Component provider="" safes={List([])} />
))
.add('Safe List whith 2 safes', () => {
const safes = List([SafeFactory.oneOwnerSafe, SafeFactory.twoOwnersSafe])
const safes = List([SafeFactory.oneOwnerSafe(), SafeFactory.twoOwnersSafe()])
return (
<Component provider="METAMASK" safes={safes} />
)

View File

@ -1,9 +1,9 @@
// @flow
import { createStructuredSelector } from 'reselect'
import { safesListSelector } from '~/routes/safeList/store/selectors'
import { safesByOwnerSelector } from '~/routes/safeList/store/selectors'
import { providerNameSelector } from '~/wallets/store/selectors/index'
export default createStructuredSelector({
safes: safesListSelector,
safes: safesByOwnerSelector,
provider: providerNameSelector,
})

View File

@ -1,7 +1,26 @@
// @flow
import { List, Map } from 'immutable'
import { createSelector, type Selector } from 'reselect'
import { type GlobalState } from '~/store/index'
import { type Safe } from '~/routes/safe/store/model/safe'
import { userAccountSelector } from '~/wallets/store/selectors/index'
import { type Owner } from '~/routes/safe/store/model/owner'
export const safesMapSelector = (state: GlobalState): Map<string, Safe> => state.safes
export const safesListSelector = (state: GlobalState): List<Safe> => state.safes.toList()
const safesListSelector: Selector<GlobalState, {}, List<Safe>> = createSelector(
safesMapSelector,
(safes: Map<string, Safe>): List<Safe> => safes.toList(),
)
export const safesByOwnerSelector: Selector<GlobalState, {}, List<Safe>> = createSelector(
userAccountSelector,
safesListSelector,
(userAddress: string, safes: List<Safe>): List<Safe> =>
safes.filter((safe: Safe) =>
safe.owners.filter((owner: Owner) => {
const ownerLower = owner.get('address').toLowerCase()
const userLower = userAddress.toLowerCase()
return ownerLower === userLower
}).count() > 0),
)

View File

@ -2,41 +2,110 @@
import { List, Map } from 'immutable'
import { SAFE_REDUCER_ID } from '~/routes/safe/store/reducer/safe'
import { type Safe } from '~/routes/safe/store/model/safe'
import { getProviderInfo } from '~/wallets/getWeb3'
import { SafeFactory } from '~/routes/safe/store/test/builder/safe.builder'
import { safesListSelector } from '../selectors'
import { PROVIDER_REDUCER_ID } from '~/wallets/store/reducer/provider'
import { makeProvider, type Provider } from '~/wallets/store/model/provider'
import { safesByOwnerSelector } from '../selectors'
const safesListSelectorTests = () => {
describe('Safes Selector[safesSelector]', () => {
let walletRecord: Provider
beforeEach(async () => {
const provider = await getProviderInfo()
walletRecord = makeProvider(provider)
})
describe('Safes Selector[safesByOwnerSelector]', () => {
it('should return empty list when no safes', () => {
// GIVEN
const reduxStore = {
[PROVIDER_REDUCER_ID]: walletRecord,
[SAFE_REDUCER_ID]: Map(),
providers: undefined,
balances: undefined,
}
const emptyList = List([])
// WHEN
const safes = safesListSelector(reduxStore)
const safes = safesByOwnerSelector(reduxStore, {})
// THEN
expect(safes).toEqual(emptyList)
})
it('should return a list of size 2 when 2 safes are created', () => {
it('should return a list of size 0 when 0 of 2 safes contains the user as owner', () => {
// GIVEN
let map: Map<string, Safe> = Map()
map = map.set('fooAddress', SafeFactory.oneOwnerSafe)
map = map.set('barAddress', SafeFactory.twoOwnersSafe)
map = map.set('fooAddress', SafeFactory.oneOwnerSafe('foo'))
map = map.set('barAddress', SafeFactory.twoOwnersSafe('foo', 'bar'))
const reduxStore = {
[PROVIDER_REDUCER_ID]: walletRecord,
[SAFE_REDUCER_ID]: map,
providers: undefined,
balances: undefined,
}
// WHEN
const safes = safesListSelector(reduxStore)
const safes = safesByOwnerSelector(reduxStore, {})
// THEN
expect(safes.count()).toEqual(0)
})
it('should return a list of size 1 when 1 of 2 safes contains the user as owner', () => {
// GIVEN
let map: Map<string, Safe> = Map()
map = map.set('fooAddress', SafeFactory.oneOwnerSafe(walletRecord.account))
map = map.set('barAddress', SafeFactory.twoOwnersSafe('foo', 'bar'))
const reduxStore = {
[PROVIDER_REDUCER_ID]: walletRecord,
[SAFE_REDUCER_ID]: map,
balances: undefined,
}
// WHEN
const safes = safesByOwnerSelector(reduxStore, {})
// THEN
expect(safes.count()).toEqual(1)
})
it('should return a list of size 2 when 2 of 2 safes contains the user as owner', () => {
// GIVEN
let map: Map<string, Safe> = Map()
const userAccount = walletRecord.account
map = map.set('fooAddress', SafeFactory.oneOwnerSafe(userAccount))
map = map.set('barAddress', SafeFactory.twoOwnersSafe('foo', userAccount))
const reduxStore = {
[SAFE_REDUCER_ID]: map,
[PROVIDER_REDUCER_ID]: walletRecord,
balances: undefined,
}
// WHEN
const safes = safesByOwnerSelector(reduxStore, {})
// THEN
expect(safes.count()).toEqual(2)
expect(safes.get(0)).not.toEqual(safes.get(1))
})
it('should return safes under owners case-insensitive', () => {
// GIVEN
let map: Map<string, Safe> = Map()
const userAccountUpper = walletRecord.account.toUpperCase()
map = map.set('fooAddress', SafeFactory.oneOwnerSafe(userAccountUpper))
map = map.set('barAddress', SafeFactory.twoOwnersSafe('foo', userAccountUpper))
const reduxStore = {
[SAFE_REDUCER_ID]: map,
[PROVIDER_REDUCER_ID]: walletRecord,
balances: undefined,
}
// WHEN
const safes = safesByOwnerSelector(reduxStore, {})
// THEN
expect(safes.count()).toEqual(2)

View File

@ -5,14 +5,31 @@ import { ensureOnce } from '~/utils/singleton'
import { getWeb3 } from '~/wallets/getWeb3'
import GnosisSafeSol from '#/GnosisSafeTeamEdition.json'
import ProxyFactorySol from '#/ProxyFactory.json'
import CreateAndAddModule from '#/CreateAndAddModule.json'
import CreateAndAddModules from '#/CreateAndAddModules.json'
import DailyLimitModule from '#/DailyLimitModule.json'
let proxyFactoryMaster
let createAndAddExtensionMaster
let createAndAddModuleMaster
let safeMaster
let dailyLimitMaster
const createModuleDataWrapper = () => {
const web3 = getWeb3()
// eslint-disable-next-line
return web3.eth.contract([{"constant":false,"inputs":[{"name":"data","type":"bytes"}],"name":"setup","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}])
}
const getModuleDataWrapper = ensureOnce(createModuleDataWrapper)
function createAndAddModulesData(dataArray) {
const ModuleDataWrapper = getModuleDataWrapper()
const mw = ModuleDataWrapper.at(1)
// Remove method id (10) and position of data in payload (64)
return dataArray.reduce((acc, data) => acc + mw.setup.getData(data).substr(74), '0x')
}
const createGnosisSafeContract = (web3: any) => {
const gnosisSafe = contract(GnosisSafeSol)
gnosisSafe.setProvider(web3.currentProvider)
@ -28,7 +45,7 @@ const createProxyFactoryContract = (web3: any) => {
}
const createAddExtensionContract = (web3: any) => {
const createAndAddModule = contract(CreateAndAddModule)
const createAndAddModule = contract(CreateAndAddModules)
createAndAddModule.setProvider(web3.currentProvider)
return createAndAddModule
@ -62,9 +79,9 @@ const createMasterCopies = async () => {
// Create AddExtension Master Copy
const CreateAndAddExtension = getCreateAddExtensionContract(web3)
try {
createAndAddExtensionMaster = await CreateAndAddExtension.deployed()
createAndAddModuleMaster = await CreateAndAddExtension.deployed()
} catch (err) {
createAndAddExtensionMaster = await CreateAndAddExtension.new({ from: userAccount, gas: '5000000' })
createAndAddModuleMaster = await CreateAndAddExtension.new({ from: userAccount, gas: '5000000' })
}
// Initialize safe master copy
@ -95,11 +112,13 @@ const getSafeDataBasedOn = async (accounts, numConfirmations, dailyLimitInEth) =
const proxyFactoryData = await proxyFactoryMaster.contract.createProxy
.getData(dailyLimitMaster.address, moduleData)
const createAndAddExtensionData = createAndAddExtensionMaster.contract.createAndAddModule
.getData(proxyFactoryMaster.address, proxyFactoryData)
const modulesCreationData = createAndAddModulesData([proxyFactoryData])
const createAndAddModuleData = createAndAddModuleMaster.contract.createAndAddModules
.getData(proxyFactoryMaster.address, modulesCreationData)
return safeMaster.contract.setup
.getData(accounts, numConfirmations, createAndAddExtensionMaster.address, createAndAddExtensionData)
.getData(accounts, numConfirmations, createAndAddModuleMaster.address, createAndAddModuleData)
}
export const deploySafeContract = async (