aboutsummaryrefslogtreecommitdiffstats
path: root/packages/contracts/src/contracts/current/protocol/AssetProxyOwner/AssetProxyOwner.sol
blob: 79f64312f52fb39f626bb569a13d349db4da32b2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/*

  Copyright 2018 ZeroEx Intl.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

*/

pragma solidity ^0.4.10;

import "../../multisig/MultiSigWalletWithTimeLock.sol";
import "../../utils/LibBytes/LibBytes.sol";

contract AssetProxyOwner is
    MultiSigWalletWithTimeLock
{
    using LibBytes for bytes;

    event AssetProxyRegistration(address assetProxyContract, bool isRegistered);

    // Mapping of AssetProxy contract address =>
    // if this contract is allowed to call the AssetProxy's removeAuthorizedAddress method without a time lock.
    mapping (address => bool) public isAssetProxyRegistered;

    bytes4 constant REMOVE_AUTHORIZED_ADDRESS_SELECTOR = bytes4(keccak256("removeAuthorizedAddress(address)"));

    /// @dev Function will revert if the transaction does not call `removeAuthorizedAddress`
    ///      on an approved AssetProxy contract.
    modifier validRemoveAuthorizedAddressTx(uint256 transactionId) {
        Transaction storage tx = transactions[transactionId];
        require(isAssetProxyRegistered[tx.destination]);
        require(tx.data.readBytes4(0) == REMOVE_AUTHORIZED_ADDRESS_SELECTOR);
        _;
    }

    /// @dev Contract constructor sets initial owners, required number of confirmations,
    ///      time lock, and list of AssetProxy addresses.
    /// @param _owners List of initial owners.
    /// @param _assetProxyContracts Array of AssetProxy contract addresses.
    /// @param _required Number of required confirmations.
    /// @param _secondsTimeLocked Duration needed after a transaction is confirmed and before it becomes executable, in seconds.
    function AssetProxyOwner(
        address[] memory _owners,
        address[] memory _assetProxyContracts,
        uint256 _required,
        uint256 _secondsTimeLocked
    )
        public
        MultiSigWalletWithTimeLock(_owners, _required, _secondsTimeLocked)
    {
        for (uint256 i = 0; i < _assetProxyContracts.length; i++) {
            address assetProxy = _assetProxyContracts[i];
            require(assetProxy != address(0));
            isAssetProxyRegistered[assetProxy] = true;
        }
    }

    /// @dev Registers or deregisters an AssetProxy to be able to execute
    ///      removeAuthorizedAddress without a timelock.
    /// @param assetProxyContract Address of AssetProxy contract.
    /// @param isRegistered Status of approval for AssetProxy contract.
    function registerAssetProxy(address assetProxyContract, bool isRegistered)
        public
        onlyWallet
        notNull(assetProxyContract)
    {
        isAssetProxyRegistered[assetProxyContract] = isRegistered;
        AssetProxyRegistration(assetProxyContract, isRegistered);
    }

    /// @dev Allows execution of removeAuthorizedAddress without time lock.
    /// @param transactionId Transaction ID.
    function executeRemoveAuthorizedAddress(uint256 transactionId)
        public
        notExecuted(transactionId)
        fullyConfirmed(transactionId)
        validRemoveAuthorizedAddressTx(transactionId)
    {
        Transaction storage tx = transactions[transactionId];
        tx.executed = true;
        if (tx.destination.call.value(tx.value)(tx.data))
            Execution(transactionId);
        else {
            ExecutionFailure(transactionId);
            tx.executed = false;
        }
    }
}