Skip to content

Commit 56a5aa0

Browse files
Merge branch 'develop' into master
2 parents c4d04d9 + 813a8a7 commit 56a5aa0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+747
-372
lines changed

.circleci/config.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,9 @@ step_setup_solc_select: &step_setup_solc_select
4444
run:
4545
name: "Setup solc-select"
4646
command: |
47-
git clone https://github.com/crytic/solc-select.git
48-
bash ./solc-select/scripts/install.sh
47+
sudo pip3 install solc-select
48+
solc-select install 0.5.4
49+
solc-select install 0.6.12
4950
jobs:
5051
unit-test:
5152
<<: *job_common
@@ -115,8 +116,6 @@ jobs:
115116
name: "Check TokenPriceRegistry tokens for ERC20 compliance"
116117
command: |
117118
export PATH=/home/circleci/.solc-select:$PATH
118-
echo "export PATH=/home/circleci/.solc-select:$PATH" >> ~/.bashrc
119-
solc --version
120119
npm run validate:erc20
121120
- run:
122121
name: "Run slither on infrastructure contracts based on solc 0.5"

.github/ISSUE_TEMPLATE/custom.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
name: Custom issue template
3+
about: Describe this issue template's purpose here.
4+
title: ''
5+
labels: ''
6+
assignees: ''
7+
8+
---
9+
10+
<!--- For issues with the Argent app, please email [email protected] -->
11+
12+
## Issue description

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ tmp
55
bin
66
.outputParameter
77
flatten
8-
8+
flat
99
## Core latex/pdflatex auxiliary files:
1010
*.aux
1111
*.lof

contracts/infrastructure/WalletFactory.sol

Lines changed: 98 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import "./base/Managed.sol";
2323
import "./storage/IGuardianStorage.sol";
2424
import "./IModuleRegistry.sol";
2525
import "../modules/common/IVersionManager.sol";
26+
import "../modules/common/Utils.sol";
2627

2728
/**
2829
* @title WalletFactory
@@ -31,56 +32,40 @@ import "../modules/common/IVersionManager.sol";
3132
*/
3233
contract WalletFactory is Owned, Managed {
3334

35+
address constant internal ETH_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
36+
3437
// The address of the module dregistry
3538
address public moduleRegistry;
3639
// The address of the base wallet implementation
3740
address public walletImplementation;
3841
// The address of the GuardianStorage
3942
address public guardianStorage;
43+
// The recipient of the refund
44+
address public refundAddress;
4045

4146
// *************** Events *************************** //
4247

4348
event ModuleRegistryChanged(address addr);
44-
event WalletCreated(address indexed wallet, address indexed owner, address indexed guardian);
49+
event RefundAddressChanged(address addr);
50+
event WalletCreated(address indexed wallet, address indexed owner, address indexed guardian, address refundToken, uint256 refundAmount);
4551

4652
// *************** Constructor ********************** //
4753

4854
/**
4955
* @notice Default constructor.
5056
*/
51-
constructor(address _moduleRegistry, address _walletImplementation, address _guardianStorage) public {
57+
constructor(address _moduleRegistry, address _walletImplementation, address _guardianStorage, address _refundAddress) public {
5258
require(_moduleRegistry != address(0), "WF: ModuleRegistry address not defined");
5359
require(_walletImplementation != address(0), "WF: WalletImplementation address not defined");
5460
require(_guardianStorage != address(0), "WF: GuardianStorage address not defined");
61+
require(_refundAddress != address(0), "WF: refund address not defined");
5562
moduleRegistry = _moduleRegistry;
5663
walletImplementation = _walletImplementation;
5764
guardianStorage = _guardianStorage;
65+
refundAddress = _refundAddress;
5866
}
5967

6068
// *************** External Functions ********************* //
61-
/**
62-
* @notice Lets the manager create a wallet for an owner account.
63-
* The wallet is initialised with the version manager module, a version number and a first guardian.
64-
* The wallet is created using the CREATE opcode.
65-
* @param _owner The account address.
66-
* @param _versionManager The version manager module
67-
* @param _guardian The guardian address.
68-
* @param _version The version of the feature bundle.
69-
*/
70-
function createWallet(
71-
address _owner,
72-
address _versionManager,
73-
address _guardian,
74-
uint256 _version
75-
)
76-
external
77-
onlyManager
78-
{
79-
validateInputs(_owner, _versionManager, _guardian, _version);
80-
Proxy proxy = new Proxy(walletImplementation);
81-
address payable wallet = address(proxy);
82-
configureWallet(BaseWallet(wallet), _owner, _versionManager, _guardian, _version);
83-
}
8469

8570
/**
8671
* @notice Lets the manager create a wallet for an owner account at a specific address.
@@ -97,7 +82,10 @@ contract WalletFactory is Owned, Managed {
9782
address _versionManager,
9883
address _guardian,
9984
bytes32 _salt,
100-
uint256 _version
85+
uint256 _version,
86+
uint256 _refundAmount,
87+
address _refundToken,
88+
bytes calldata _ownerSignature
10189
)
10290
external
10391
onlyManager
@@ -108,6 +96,15 @@ contract WalletFactory is Owned, Managed {
10896
Proxy proxy = new Proxy{salt: newsalt}(walletImplementation);
10997
address payable wallet = address(proxy);
11098
configureWallet(BaseWallet(wallet), _owner, _versionManager, _guardian, _version);
99+
if (_refundAmount > 0 && _ownerSignature.length == 65) {
100+
validateAndRefund(wallet, _owner, _refundAmount, _refundToken, _ownerSignature);
101+
}
102+
// remove the factory from the authorised modules
103+
BaseWallet(wallet).authoriseModule(address(this), false);
104+
105+
// emit event
106+
emit WalletCreated(wallet, _owner, _guardian, _refundToken, _refundAmount);
107+
111108
return wallet;
112109
}
113110

@@ -148,6 +145,16 @@ contract WalletFactory is Owned, Managed {
148145
emit ModuleRegistryChanged(_moduleRegistry);
149146
}
150147

148+
/**
149+
* @notice Lets the owner change the refund address.
150+
* @param _refundAddress The address to use for refunds.
151+
*/
152+
function changeRefundAddress(address _refundAddress) external onlyOwner {
153+
require(_refundAddress != address(0), "WF: address cannot be null");
154+
refundAddress = _refundAddress;
155+
emit RefundAddressChanged(_refundAddress);
156+
}
157+
151158
/**
152159
* @notice Inits the module for a wallet by doing nothing.
153160
* The method can only be called by the wallet itself.
@@ -189,12 +196,6 @@ contract WalletFactory is Owned, Managed {
189196

190197
// upgrade the wallet
191198
IVersionManager(_versionManager).upgradeWallet(address(_wallet), _version);
192-
193-
// remove the factory from the authorised modules
194-
_wallet.authoriseModule(address(this), false);
195-
196-
// emit event
197-
emit WalletCreated(address(_wallet), _owner, _guardian);
198199
}
199200

200201
/**
@@ -222,4 +223,68 @@ contract WalletFactory is Owned, Managed {
222223
require(_guardian != (address(0)), "WF: guardian cannot be null");
223224
require(_version > 0, "WF: invalid _version");
224225
}
225-
}
226+
227+
/**
228+
* @notice Refunds the creation of the wallet when provided with a valid signature from the wallet owner.
229+
* @param _wallet The wallet created
230+
* @param _owner The owner address
231+
* @param _refundAmount The amount to refund
232+
* @param _refundToken The token to use for the refund
233+
* @param _ownerSignature A signature from the wallet owner approving the refund amount and token.
234+
*/
235+
function validateAndRefund(
236+
address _wallet,
237+
address _owner,
238+
uint256 _refundAmount,
239+
address _refundToken,
240+
bytes memory _ownerSignature
241+
)
242+
internal
243+
{
244+
bytes32 signedHash = keccak256(abi.encodePacked(
245+
"\x19Ethereum Signed Message:\n32",
246+
keccak256(abi.encodePacked(_refundAmount, _refundToken))
247+
));
248+
address signer = Utils.recoverSigner(signedHash, _ownerSignature, 0);
249+
if (signer == _owner) {
250+
if (_refundToken == ETH_TOKEN) {
251+
invokeWallet(_wallet, refundAddress, _refundAmount, "");
252+
} else {
253+
bytes memory methodData = abi.encodeWithSignature("transfer(address,uint256)", refundAddress, _refundAmount);
254+
bytes memory transferSuccessBytes = invokeWallet(_wallet, _refundToken, 0, methodData);
255+
if (transferSuccessBytes.length > 0) {
256+
require(abi.decode(transferSuccessBytes, (bool)), "WF: Refund transfer failed");
257+
}
258+
}
259+
}
260+
}
261+
262+
/**
263+
* @notice Invoke the wallet to execute the refund transfer.
264+
* @param _wallet The wallet
265+
* @param _to The destination of the call
266+
* @param _value The value of the call
267+
* @param _data The data associated to the call
268+
*/
269+
function invokeWallet(
270+
address _wallet,
271+
address _to,
272+
uint256 _value,
273+
bytes memory _data
274+
)
275+
internal
276+
returns (bytes memory _res)
277+
{
278+
bool success;
279+
(success, _res) = _wallet.call(abi.encodeWithSignature("invoke(address,uint256,bytes)", _to, _value, _data));
280+
if (success) {
281+
(_res) = abi.decode(_res, (bytes));
282+
} else {
283+
// solhint-disable-next-line no-inline-assembly
284+
assembly {
285+
returndatacopy(0, 0, returndatasize())
286+
revert(0, returndatasize())
287+
}
288+
}
289+
}
290+
}

deployment/2_deploy_contracts.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ async function main() {
7070
walletRootEns, utils.namehash(walletRootEns), newConfig.ENS.ensRegistry, ENSResolverWrapper.address);
7171
// Deploy the Wallet Factory
7272
const WalletFactoryWrapper = await WalletFactory.new(
73-
ModuleRegistryWrapper.address, BaseWalletWrapper.address, GuardianStorageWrapper.address);
73+
ModuleRegistryWrapper.address, BaseWalletWrapper.address, GuardianStorageWrapper.address, prevConfig.backend.refundCollector);
7474

7575
// Deploy and configure Maker Registry
7676
const ScdMcdMigrationWrapper = await ScdMcdMigration.at(newConfig.defi.maker.migration);

package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"test": "npx truffle test --compile-none",
2525
"ctest": "npm run compile && npm run test",
2626
"provision:lib:artefacts": "bash ./scripts/provision_lib_artefacts.sh",
27-
"test:coverage": "node scripts/coverage.js && istanbul check-coverage --statements 82 --branches 78 --functions 82 --lines 82",
27+
"test:coverage": "COVERAGE=1 node scripts/coverage.js && istanbul check-coverage --statements 82 --branches 78 --functions 82 --lines 82",
2828
"lint:js": "eslint .",
2929
"lint:contracts": "npx solhint contracts/**/*.sol && npx solhint contracts/**/**/*.sol",
3030
"test:deployment": "./scripts/deploy.sh --no-compile development `seq 1 6`",

scripts/configReader.js renamed to scripts/config_reader.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Script to print environment configuration from AWS.
33
//
44
// Can be executed (from the project root as we're loading .env file from root via `dotenv`) as:
5-
// bash ./scripts/execute_script.sh --no-compile scripts/configReader.js <network>
5+
// bash ./scripts/execute_script.sh --no-compile scripts/config_reader.js <network>
66
//
77
// where:
88
// - network = [test, staging, prod]
@@ -40,6 +40,4 @@ async function main() {
4040
configurator._validate();
4141
}
4242

43-
main().catch((err) => {
44-
throw err;
45-
});
43+
module.exports = (cb) => main().then(cb).catch(cb);

scripts/deploy_custom_upgrader.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,20 @@ async function main() {
2323
"0xE739e93dD617D28216dB669AcFdbFC70BF95663c",
2424
];
2525
const upgraderName = "0x4ef2f261_0xee7263da";
26-
2726
const ModuleRegistryWrapper = await ModuleRegistry.at(config.contracts.ModuleRegistry);
2827
const MultiSigWrapper = await MultiSig.at(config.contracts.MultiSigWallet);
2928
const multisigExecutor = new MultisigExecutor(MultiSigWrapper, deploymentAccount, config.multisig.autosign);
3029

3130
const UpgraderWrapper = await Upgrader.new(
3231
modulesToRemove,
3332
modulesToAdd,
33+
{ gas: 1200000 }
3434
);
35-
3635
await multisigExecutor.executeCall(ModuleRegistryWrapper, "registerUpgrader",
37-
[UpgraderWrapper.address, utils.asciiToBytes32(upgraderName)]);
36+
[UpgraderWrapper.address, utils.asciiToBytes32(upgraderName)], { gas: 500000 });
37+
38+
await multisigExecutor.executeCall(ModuleRegistryWrapper, "registerModule",
39+
[UpgraderWrapper.address, utils.asciiToBytes32(upgraderName)], { gas: 500000 });
3840
}
3941

40-
main().catch((err) => {
41-
throw err;
42-
});
42+
module.exports = (cb) => main().then(cb).catch(cb);

scripts/deploy_defi.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,4 @@ async function main() {
9898
console.log("********************************");
9999
}
100100

101-
main().catch((err) => {
102-
throw err;
103-
});
101+
module.exports = (cb) => main().then(cb).catch(cb);

0 commit comments

Comments
 (0)