ETH Price: $2,557.63 (-0.97%)

Transaction Decoder

Block:
10570753 at Aug-01-2020 01:03:48 AM +UTC
Transaction Fee:
0.033304966 ETH $85.18
Gas Used:
724,021 Gas / 46 Gwei

Account State Difference:

  Address   Before After State Difference Code
0xdAE0aca4...B3B0495fE
(DeFireX: Deployer)
8.297898928306922528 Eth
Nonce: 1365
8.264593962306922528 Eth
Nonce: 1366
0.033304966
(Ethermine)
883.1390060784723708 Eth883.1723110444723708 Eth0.033304966
0xfACd9A6f...6d9DCAE01
0 Eth
Nonce: 0
0 Eth
Nonce: 1
From: 0 To: 68443738607301888435145996585426240542618037971122800049305818310931483616799641514214051017102183913352615279595429514655268746803640485882899688506499490829898583492378220170299639521259223095862990963989628189502584774320644161498403789448199812692777322066142521885708947747005317311811001579913651425873442595067357639896362939680558586441985565168455139386687192912942729745196200068669389529199433976413530757296943899703927719920821963494969745140860508740734455628720742186906776617175298209993704607988400844944846339793474251556911909265708952940938783778657480472776443706760116417256387698723390650396269097214650872350597128123276247150942443250883289279468353886733951302163897312831698205202680230047723296646307289246312142100397405510917971078524454835315490423485598891082047460904692721349838305380836890285523039579833603869025713245438115047296837381562813678463365072963516447812819000782074873859625102916723315215973743770965999570240940438694214162503751296637587162717135034701816078046712256771001316025747694198552533425175302028428112955926478291305331234220362302752021089607841344660365719457823874542049273309297311819864519264690765220945824221464121155586793897501819389582327813209645634140912288610895865510353742337913790336162340320867796346183017683156266137727813851050774292607267520744255934946709117942970459403107046042448851635956821858560622072647290737323169369218161659908564405068546390834516551407102299506038600341806389396913281681897875298777190140328957998932273677438499275840843113108022614242005948179747818058525266829492730124111718965466976772942147568855559814963267678040954384511496367672896310398621079959516987805364019114123550112789904178141386111752839482018319157549912854094590496199837536837823191325473908252334704237641122423305061952934515093100993420892541618021572819285648747964243790094052957944687368873711710943738193143831766155272408133630971912546439980826522641828027901758185391825049550376982124926563439006245942011188232590179688622505127103332101566649256547984431013412524196689353315772014535246607381382963370606375298465795344038361131582349452378459318771217579707167323835693738471058738998342135509009324556806332820512492322956043498255154308904445255126179038560690979788510476396973450733763256685161103964461850023891529755829669014014691050449079121011379528672610368267433400988480169349937497617476413444809877982154476566296117173356249164743050437754588642547132940284490063994728851802558521350844931415513721136098558532106904651413173092441666143396426380788767180973117094475102572916002059348813942277294336936355959774989155110679272752811028553819537386784577575920676664509126266981012265992820839821022642870468466245384615756705156169181968007801194736089554772962733033199120978079707928117602167883508674847797847586458474376313759965898474177712326834798735081061847867813958476509808340305603012982614010204639159945067678120657601641588192107828077499893036857688949224582206658682627682289218732176219834195800534767455644875078287638952514974378970930071479609430823754707648826718244550617794881398683932875668068123067407952504744422736488198022874105426397927949498450997765699582859521699488335078965692123395232340216884393112540125449807802426622792781006666067690819285150333226447107362874049082912916534014373292011524873722160410928504140576893367832303117122926816027327591664283932339921522468941755490806694022423300642107773311250697740624503805055575527891423877056475133089069895521748946205364251991313376172304889784550606880019756769403932192212764283689947024734866141700020936500485463411319032733889090347923274196986981604991865252876024079701748808880806957778728315073685731535408436706253781313231089703392429533250622476968311033773568264867347009077379309433041872683702468437521691389697033429024181154669344071771418147519131406057356999881046210711023376162492065597310787239874379680159505930726595214724285818650396414081548572147438915096974790177898001626899810608499942843863466861216718189335204890811749446503305421666649501728555502356521676552896196614280486419117873625583670347428530935582937087325450802084756515202208867596602577198537804012038815302419539162350136738328165203153171265041095078215751097806691144780280816081363309757624756571353948317134607477875216872541711637778806211349576761089914227116549982853821124097572660204343099040072895657093474104712362574587936760130564659665860040799262176831928540171031389451469995512541729473622372207528278634639288074767931803616399666229150172469359812906019430457184169926317220125956362161287423905042365402862333704861143433312460824118777054854000989490889254965377463587071965205086953624046465423633927239742994528789996842429203122430944471068123302023750929792177361122135174273515200190750227606146723219974994390139530276896096025314510240202834355217222217743653937267108220190541748477515410588090535049452705367298190967221979986418519622004238856894337998116454539489779519703019514394468950801733754416985321498743071148618995124596874921176791347570296318450493001685072901423866644001392789790512049778050726719400599917454399385121254906492740707885978797422896549583141894337784472966809009549721267226825829960856498965106166115237226754797811834816410079627261796364453071596092763071671225603197005327570056897586401419479806243636903771091657806337972214475370566187468012480185369616471409862137132452126651275014214197185671059178781840595326501516724912532642888414483420035724784732051157875753735829178290393775603753

Execution Trace

AdminUpgradeabilityProxy.60806040( )
  • DfDepositToken.initialize( _name=DeFireX DAI, _symbol=dDAI, _decimals=18, _controller=0xb942ca22e0eb0f2524F53f999aE33fD3B2D58E3E )
    File 1 of 2: AdminUpgradeabilityProxy
    // File: @openzeppelin/upgrades/contracts/upgradeability/Proxy.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @title Proxy
     * @dev Implements delegation of calls to other contracts, with proper
     * forwarding of return values and bubbling of failures.
     * It defines a fallback function that delegates all calls to the address
     * returned by the abstract _implementation() internal function.
     */
    contract Proxy {
      /**
       * @dev Fallback function.
       * Implemented entirely in `_fallback`.
       */
      function () payable external {
        _fallback();
      }
    
      /**
       * @return The Address of the implementation.
       */
      function _implementation() internal view returns (address);
    
      /**
       * @dev Delegates execution to an implementation contract.
       * This is a low level function that doesn't return to its internal call site.
       * It will return to the external caller whatever the implementation returns.
       * @param implementation Address to delegate.
       */
      function _delegate(address implementation) internal {
        assembly {
          // Copy msg.data. We take full control of memory in this inline assembly
          // block because it will not return to Solidity code. We overwrite the
          // Solidity scratch pad at memory position 0.
          calldatacopy(0, 0, calldatasize)
    
          // Call the implementation.
          // out and outsize are 0 because we don't know the size yet.
          let result := delegatecall(gas, implementation, 0, calldatasize, 0, 0)
    
          // Copy the returned data.
          returndatacopy(0, 0, returndatasize)
    
          switch result
          // delegatecall returns 0 on error.
          case 0 { revert(0, returndatasize) }
          default { return(0, returndatasize) }
        }
      }
    
      /**
       * @dev Function that is run as the first thing in the fallback function.
       * Can be redefined in derived contracts to add functionality.
       * Redefinitions must call super._willFallback().
       */
      function _willFallback() internal {
      }
    
      /**
       * @dev fallback implementation.
       * Extracted to enable manual triggering.
       */
      function _fallback() internal {
        _willFallback();
        _delegate(_implementation());
      }
    }
    
    // File: @openzeppelin/upgrades/contracts/utils/Address.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * Utility library of inline functions on addresses
     *
     * Source https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-solidity/v2.1.3/contracts/utils/Address.sol
     * This contract is copied here and renamed from the original to avoid clashes in the compiled artifacts
     * when the user imports a zos-lib contract (that transitively causes this contract to be compiled and added to the
     * build/artifacts folder) as well as the vanilla Address implementation from an openzeppelin version.
     */
    library OpenZeppelinUpgradesAddress {
        /**
         * Returns whether the target address is a contract
         * @dev This function will return false if invoked during the constructor of a contract,
         * as the code is not actually created until after the constructor finishes.
         * @param account address of the account to check
         * @return whether the target address is a contract
         */
        function isContract(address account) internal view returns (bool) {
            uint256 size;
            // XXX Currently there is no better way to check if there is a contract in an address
            // than to check the size of the code at that address.
            // See https://ethereum.stackexchange.com/a/14016/36603
            // for more details about how this works.
            // TODO Check this again before the Serenity release, because all addresses will be
            // contracts then.
            // solhint-disable-next-line no-inline-assembly
            assembly { size := extcodesize(account) }
            return size > 0;
        }
    }
    
    // File: @openzeppelin/upgrades/contracts/upgradeability/BaseUpgradeabilityProxy.sol
    
    pragma solidity ^0.5.0;
    
    
    
    /**
     * @title BaseUpgradeabilityProxy
     * @dev This contract implements a proxy that allows to change the
     * implementation address to which it will delegate.
     * Such a change is called an implementation upgrade.
     */
    contract BaseUpgradeabilityProxy is Proxy {
      /**
       * @dev Emitted when the implementation is upgraded.
       * @param implementation Address of the new implementation.
       */
      event Upgraded(address indexed implementation);
    
      /**
       * @dev Storage slot with the address of the current implementation.
       * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
       * validated in the constructor.
       */
      bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
    
      /**
       * @dev Returns the current implementation.
       * @return Address of the current implementation
       */
      function _implementation() internal view returns (address impl) {
        bytes32 slot = IMPLEMENTATION_SLOT;
        assembly {
          impl := sload(slot)
        }
      }
    
      /**
       * @dev Upgrades the proxy to a new implementation.
       * @param newImplementation Address of the new implementation.
       */
      function _upgradeTo(address newImplementation) internal {
        _setImplementation(newImplementation);
        emit Upgraded(newImplementation);
      }
    
      /**
       * @dev Sets the implementation address of the proxy.
       * @param newImplementation Address of the new implementation.
       */
      function _setImplementation(address newImplementation) internal {
        require(OpenZeppelinUpgradesAddress.isContract(newImplementation), "Cannot set a proxy implementation to a non-contract address");
    
        bytes32 slot = IMPLEMENTATION_SLOT;
    
        assembly {
          sstore(slot, newImplementation)
        }
      }
    }
    
    // File: @openzeppelin/upgrades/contracts/upgradeability/UpgradeabilityProxy.sol
    
    pragma solidity ^0.5.0;
    
    
    /**
     * @title UpgradeabilityProxy
     * @dev Extends BaseUpgradeabilityProxy with a constructor for initializing
     * implementation and init data.
     */
    contract UpgradeabilityProxy is BaseUpgradeabilityProxy {
      /**
       * @dev Contract constructor.
       * @param _logic Address of the initial implementation.
       * @param _data Data to send as msg.data to the implementation to initialize the proxied contract.
       * It should include the signature and the parameters of the function to be called, as described in
       * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.
       * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped.
       */
      constructor(address _logic, bytes memory _data) public payable {
        assert(IMPLEMENTATION_SLOT == bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1));
        _setImplementation(_logic);
        if(_data.length > 0) {
          (bool success,) = _logic.delegatecall(_data);
          require(success);
        }
      }  
    }
    
    // File: @openzeppelin/upgrades/contracts/upgradeability/BaseAdminUpgradeabilityProxy.sol
    
    pragma solidity ^0.5.0;
    
    
    /**
     * @title BaseAdminUpgradeabilityProxy
     * @dev This contract combines an upgradeability proxy with an authorization
     * mechanism for administrative tasks.
     * All external functions in this contract must be guarded by the
     * `ifAdmin` modifier. See ethereum/solidity#3864 for a Solidity
     * feature proposal that would enable this to be done automatically.
     */
    contract BaseAdminUpgradeabilityProxy is BaseUpgradeabilityProxy {
      /**
       * @dev Emitted when the administration has been transferred.
       * @param previousAdmin Address of the previous admin.
       * @param newAdmin Address of the new admin.
       */
      event AdminChanged(address previousAdmin, address newAdmin);
    
      /**
       * @dev Storage slot with the admin of the contract.
       * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
       * validated in the constructor.
       */
    
      bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
    
      /**
       * @dev Modifier to check whether the `msg.sender` is the admin.
       * If it is, it will run the function. Otherwise, it will delegate the call
       * to the implementation.
       */
      modifier ifAdmin() {
        if (msg.sender == _admin()) {
          _;
        } else {
          _fallback();
        }
      }
    
      /**
       * @return The address of the proxy admin.
       */
      function admin() external ifAdmin returns (address) {
        return _admin();
      }
    
      /**
       * @return The address of the implementation.
       */
      function implementation() external ifAdmin returns (address) {
        return _implementation();
      }
    
      /**
       * @dev Changes the admin of the proxy.
       * Only the current admin can call this function.
       * @param newAdmin Address to transfer proxy administration to.
       */
      function changeAdmin(address newAdmin) external ifAdmin {
        require(newAdmin != address(0), "Cannot change the admin of a proxy to the zero address");
        emit AdminChanged(_admin(), newAdmin);
        _setAdmin(newAdmin);
      }
    
      /**
       * @dev Upgrade the backing implementation of the proxy.
       * Only the admin can call this function.
       * @param newImplementation Address of the new implementation.
       */
      function upgradeTo(address newImplementation) external ifAdmin {
        _upgradeTo(newImplementation);
      }
    
      /**
       * @dev Upgrade the backing implementation of the proxy and call a function
       * on the new implementation.
       * This is useful to initialize the proxied contract.
       * @param newImplementation Address of the new implementation.
       * @param data Data to send as msg.data in the low level call.
       * It should include the signature and the parameters of the function to be called, as described in
       * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.
       */
      function upgradeToAndCall(address newImplementation, bytes calldata data) payable external ifAdmin {
        _upgradeTo(newImplementation);
        (bool success,) = newImplementation.delegatecall(data);
        require(success);
      }
    
      /**
       * @return The admin slot.
       */
      function _admin() internal view returns (address adm) {
        bytes32 slot = ADMIN_SLOT;
        assembly {
          adm := sload(slot)
        }
      }
    
      /**
       * @dev Sets the address of the proxy admin.
       * @param newAdmin Address of the new proxy admin.
       */
      function _setAdmin(address newAdmin) internal {
        bytes32 slot = ADMIN_SLOT;
    
        assembly {
          sstore(slot, newAdmin)
        }
      }
    
      /**
       * @dev Only fall back when the sender is not the admin.
       */
      function _willFallback() internal {
        require(msg.sender != _admin(), "Cannot call fallback function from the proxy admin");
        super._willFallback();
      }
    }
    
    // File: @openzeppelin/upgrades/contracts/upgradeability/AdminUpgradeabilityProxy.sol
    
    pragma solidity ^0.5.0;
    
    
    /**
     * @title AdminUpgradeabilityProxy
     * @dev Extends from BaseAdminUpgradeabilityProxy with a constructor for 
     * initializing the implementation, admin, and init data.
     */
    contract AdminUpgradeabilityProxy is BaseAdminUpgradeabilityProxy, UpgradeabilityProxy {
      /**
       * Contract constructor.
       * @param _logic address of the initial implementation.
       * @param _admin Address of the proxy administrator.
       * @param _data Data to send as msg.data to the implementation to initialize the proxied contract.
       * It should include the signature and the parameters of the function to be called, as described in
       * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.
       * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped.
       */
      constructor(address _logic, address _admin, bytes memory _data) UpgradeabilityProxy(_logic, _data) public payable {
        assert(ADMIN_SLOT == bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1));
        _setAdmin(_admin);
      }
    }

    File 2 of 2: DfDepositToken
    // File: @openzeppelin\upgrades\contracts\Initializable.sol
    
    pragma solidity >=0.4.24 <0.7.0;
    
    
    /**
     * @title Initializable
     *
     * @dev Helper contract to support initializer functions. To use it, replace
     * the constructor with a function that has the `initializer` modifier.
     * WARNING: Unlike constructors, initializer functions must be manually
     * invoked. This applies both to deploying an Initializable contract, as well
     * as extending an Initializable contract via inheritance.
     * WARNING: When used with inheritance, manual care must be taken to not invoke
     * a parent initializer twice, or ensure that all initializers are idempotent,
     * because this is not dealt with automatically as with constructors.
     */
    contract Initializable {
    
      /**
       * @dev Indicates that the contract has been initialized.
       */
      bool private initialized;
    
      /**
       * @dev Indicates that the contract is in the process of being initialized.
       */
      bool private initializing;
    
      /**
       * @dev Modifier to use in the initializer function of a contract.
       */
      modifier initializer() {
        require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized");
    
        bool isTopLevelCall = !initializing;
        if (isTopLevelCall) {
          initializing = true;
          initialized = true;
        }
    
        _;
    
        if (isTopLevelCall) {
          initializing = false;
        }
      }
    
      /// @dev Returns true if and only if the function is running in the constructor
      function isConstructor() private view returns (bool) {
        // extcodesize checks the size of the code stored in an address, and
        // address returns the current address. Since the code is still not
        // deployed when running a constructor, any checks on its code size will
        // yield zero, making it an effective way to detect if a contract is
        // under construction or not.
        address self = address(this);
        uint256 cs;
        assembly { cs := extcodesize(self) }
        return cs == 0;
      }
    
      // Reserved storage space to allow for layout changes in the future.
      uint256[50] private ______gap;
    }
    
    // File: contracts\interfaces\IERC20.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @dev Interface of the ERC20 standard as defined in the EIP. Does not include
     * the optional functions; to access them see {ERC20Detailed}.
     */
    interface IERC20 {
        /**
         * @dev Returns the amount of tokens in existence.
         */
        function totalSupply() external view returns (uint256);
    
        /**
         * @dev Returns the amount of tokens owned by `account`.
         */
        function balanceOf(address account) external view returns (uint256);
    
        /**
         * @dev Moves `amount` tokens from the caller's account to `recipient`.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * Emits a {Transfer} event.
         */
        function transfer(address recipient, uint256 amount) external returns (bool);
    
        /**
         * @dev Returns the remaining number of tokens that `spender` will be
         * allowed to spend on behalf of `owner` through {transferFrom}. This is
         * zero by default.
         *
         * This value changes when {approve} or {transferFrom} are called.
         */
        function allowance(address owner, address spender) external view returns (uint256);
    
        /**
         * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * IMPORTANT: Beware that changing an allowance with this method brings the risk
         * that someone may use both the old and the new allowance by unfortunate
         * transaction ordering. One possible solution to mitigate this race
         * condition is to first reduce the spender's allowance to 0 and set the
         * desired value afterwards:
         * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
         *
         * Emits an {Approval} event.
         */
        function approve(address spender, uint256 amount) external returns (bool);
    
        /**
         * @dev Moves `amount` tokens from `sender` to `recipient` using the
         * allowance mechanism. `amount` is then deducted from the caller's
         * allowance.
         *
         * Returns a boolean value indicating whether the operation succeeded.
         *
         * Emits a {Transfer} event.
         */
        function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
    
        /**
         * @dev Emitted when `value` tokens are moved from one account (`from`) to
         * another (`to`).
         *
         * Note that `value` may be zero.
         */
        event Transfer(address indexed from, address indexed to, uint256 value);
    
        /**
         * @dev Emitted when the allowance of a `spender` for an `owner` is set by
         * a call to {approve}. `value` is the new allowance.
         */
        event Approval(address indexed owner, address indexed spender, uint256 value);
    }
    
    // File: contracts\token\ERC20\ERC20Detailed.sol
    
    pragma solidity ^0.5.0;
    
    
    
    
    /**
     * @dev Optional functions from the ERC20 standard.
     */
    contract ERC20Detailed is Initializable, IERC20 {
        string private _name;
        string private _symbol;
        uint8 private _decimals;
    
        /**
         * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of
         * these values are immutable: they can only be set once during
         * construction.
         */
        function initialize(string memory name, string memory symbol, uint8 decimals) public initializer {
            _name = name;
            _symbol = symbol;
            _decimals = decimals;
        }
    
        /**
         * @dev Returns the name of the token.
         */
        function name() public view returns (string memory) {
            return _name;
        }
    
        /**
         * @dev Returns the symbol of the token, usually a shorter version of the
         * name.
         */
        function symbol() public view returns (string memory) {
            return _symbol;
        }
    
        /**
         * @dev Returns the number of decimals used to get its user representation.
         * For example, if `decimals` equals `2`, a balance of `505` tokens should
         * be displayed to a user as `5,05` (`505 / 10 ** 2`).
         *
         * Tokens usually opt for a value of 18, imitating the relationship between
         * Ether and Wei.
         *
         * NOTE: This information is only used for _display_ purposes: it in
         * no way affects any of the arithmetic of the contract, including
         * {IERC20-balanceOf} and {IERC20-transfer}.
         */
        function decimals() public view returns (uint8) {
            return _decimals;
        }
    
        uint256[50] private ______gap;
    }
    
    // File: contracts\utils\SafeMath.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @dev Wrappers over Solidity's arithmetic operations with added overflow
     * checks.
     *
     * Arithmetic operations in Solidity wrap on overflow. This can easily result
     * in bugs, because programmers usually assume that an overflow raises an
     * error, which is the standard behavior in high level programming languages.
     * `SafeMath` restores this intuition by reverting the transaction when an
     * operation overflows.
     *
     * Using this library instead of the unchecked operations eliminates an entire
     * class of bugs, so it's recommended to use it always.
     */
    library SafeMath {
        /**
         * @dev Returns the addition of two unsigned integers, reverting on
         * overflow.
         *
         * Counterpart to Solidity's `+` operator.
         *
         * Requirements:
         * - Addition cannot overflow.
         */
        function add(uint256 a, uint256 b) internal pure returns (uint256) {
            uint256 c = a + b;
            require(c >= a, "SafeMath: addition overflow");
    
            return c;
        }
    
        /**
         * @dev Returns the subtraction of two unsigned integers, reverting on
         * overflow (when the result is negative).
         *
         * Counterpart to Solidity's `-` operator.
         *
         * Requirements:
         * - Subtraction cannot overflow.
         */
        function sub(uint256 a, uint256 b) internal pure returns (uint256) {
            return sub(a, b, "SafeMath: subtraction overflow");
        }
    
        /**
         * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
         * overflow (when the result is negative).
         *
         * Counterpart to Solidity's `-` operator.
         *
         * Requirements:
         * - Subtraction cannot overflow.
         *
         * _Available since v2.4.0._
         */
        function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
            require(b <= a, errorMessage);
            uint256 c = a - b;
    
            return c;
        }
    
        /**
         * @dev Returns the multiplication of two unsigned integers, reverting on
         * overflow.
         *
         * Counterpart to Solidity's `*` operator.
         *
         * Requirements:
         * - Multiplication cannot overflow.
         */
        function mul(uint256 a, uint256 b) internal pure returns (uint256) {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) {
                return 0;
            }
    
            uint256 c = a * b;
            require(c / a == b, "SafeMath: multiplication overflow");
    
            return c;
        }
    
        /**
         * @dev Returns the integer division of two unsigned integers. Reverts on
         * division by zero. The result is rounded towards zero.
         *
         * Counterpart to Solidity's `/` operator. Note: this function uses a
         * `revert` opcode (which leaves remaining gas untouched) while Solidity
         * uses an invalid opcode to revert (consuming all remaining gas).
         *
         * Requirements:
         * - The divisor cannot be zero.
         */
        function div(uint256 a, uint256 b) internal pure returns (uint256) {
            return div(a, b, "SafeMath: division by zero");
        }
    
        /**
         * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
         * division by zero. The result is rounded towards zero.
         *
         * Counterpart to Solidity's `/` operator. Note: this function uses a
         * `revert` opcode (which leaves remaining gas untouched) while Solidity
         * uses an invalid opcode to revert (consuming all remaining gas).
         *
         * Requirements:
         * - The divisor cannot be zero.
         *
         * _Available since v2.4.0._
         */
        function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
            // Solidity only automatically asserts when dividing by 0
            require(b > 0, errorMessage);
            uint256 c = a / b;
            // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    
            return c;
        }
    
        /**
         * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
         * Reverts when dividing by zero.
         *
         * Counterpart to Solidity's `%` operator. This function uses a `revert`
         * opcode (which leaves remaining gas untouched) while Solidity uses an
         * invalid opcode to revert (consuming all remaining gas).
         *
         * Requirements:
         * - The divisor cannot be zero.
         */
        function mod(uint256 a, uint256 b) internal pure returns (uint256) {
            return mod(a, b, "SafeMath: modulo by zero");
        }
    
        /**
         * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
         * Reverts with custom message when dividing by zero.
         *
         * Counterpart to Solidity's `%` operator. This function uses a `revert`
         * opcode (which leaves remaining gas untouched) while Solidity uses an
         * invalid opcode to revert (consuming all remaining gas).
         *
         * Requirements:
         * - The divisor cannot be zero.
         *
         * _Available since v2.4.0._
         */
        function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
            require(b != 0, errorMessage);
            return a % b;
        }
    }
    
    // File: contracts\utils\Math.sol
    
    pragma solidity ^0.5.0;
    
    /**
     * @dev Standard math utilities missing in the Solidity language.
     */
    library Math {
        /**
         * @dev Returns the largest of two numbers.
         */
        function max(uint256 a, uint256 b) internal pure returns (uint256) {
            return a >= b ? a : b;
        }
    
        /**
         * @dev Returns the smallest of two numbers.
         */
        function min(uint256 a, uint256 b) internal pure returns (uint256) {
            return a < b ? a : b;
        }
    
        /**
         * @dev Returns the average of two numbers. The result is rounded towards
         * zero.
         */
        function average(uint256 a, uint256 b) internal pure returns (uint256) {
            // (a + b) / 2 can overflow, so we distribute
            return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
        }
    }
    
    // File: contracts\utils\Arrays.sol
    
    pragma solidity ^0.5.0;
    
    
    /**
     * @dev Collection of functions related to array types.
     */
    library Arrays {
       /**
         * @dev Searches a sorted `array` and returns the first index that contains
         * a value greater or equal to `element`. If no such index exists (i.e. all
         * values in the array are strictly less than `element`), the array length is
         * returned. Time complexity O(log n).
         *
         * `array` is expected to be sorted in ascending order, and to contain no
         * repeated elements.
         */
        function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
            if (array.length == 0) {
                return 0;
            }
    
            uint256 low = 0;
            uint256 high = array.length;
    
            while (low < high) {
                uint256 mid = Math.average(low, high);
    
                // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
                // because Math.average rounds down (it does integer division with truncation).
                if (array[mid] > element) {
                    high = mid;
                } else {
                    low = mid + 1;
                }
            }
    
            // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.
            if (low > 0 && array[low - 1] == element) {
                return low - 1;
            } else {
                return low;
            }
        }
    }
    
    // File: contracts\utils\Counters.sol
    
    pragma solidity ^0.5.16;
    
    
    
    /**
     * @title Counters
     * @author Matt Condon (@shrugs)
     * @dev Provides counters that can only be incremented or decremented by one. This can be used e.g. to track the number
     * of elements in a mapping, issuing ERC721 ids, or counting request ids.
     *
     * Include with `using Counters for Counters.Counter;`
     * Since it is not possible to overflow a 256 bit integer with increments of one, `increment` can skip the {SafeMath}
     * overflow check, thereby saving gas. This does assume however correct usage, in that the underlying `_value` is never
     * directly accessed.
     */
    library Counters {
        using SafeMath for uint256;
    
        struct Counter {
            // This variable should never be directly accessed by users of the library: interactions must be restricted to
            // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
            // this feature: see https://github.com/ethereum/solidity/issues/4637
            uint256 _value; // default: 0
        }
    
        function current(Counter storage counter) internal view returns (uint256) {
            return counter._value;
        }
    
        function increment(Counter storage counter) internal {
            // The {SafeMath} overflow check can be skipped here, see the comment at the top
            counter._value += 1;
        }
    
        function decrement(Counter storage counter) internal {
            counter._value = counter._value.sub(1);
        }
    }
    
    // File: contracts\token\ERC20\ERC20.sol
    
    pragma solidity ^0.5.0;
    
    
    
    
    
    /**
     * @dev Implementation of the {IERC20} interface.
     */
    contract ERC20 is Initializable, IERC20 {
        using SafeMath for uint256;
    
        mapping (address => uint256) internal _balances;
    
        mapping (address => mapping (address => uint256)) internal _allowances;
    
        uint256 internal _totalSupply;
    
        /**
         * @dev See {IERC20-totalSupply}.
         */
        function totalSupply() public view returns (uint256) {
            return _totalSupply;
        }
    
        /**
         * @dev See {IERC20-balanceOf}.
         */
        function balanceOf(address account) public view returns (uint256) {
            return _balances[account];
        }
    
        /**
         * @dev See {IERC20-transfer}.
         *
         * Requirements:
         *
         * - `recipient` cannot be the zero address.
         * - the caller must have a balance of at least `amount`.
         */
        function transfer(address recipient, uint256 amount) public returns (bool) {
            _transfer(msg.sender, recipient, amount);
            return true;
        }
    
        /**
         * @dev See {IERC20-allowance}.
         */
        function allowance(address owner, address spender) public view returns (uint256) {
            return _allowances[owner][spender];
        }
    
        /**
         * @dev See {IERC20-approve}.
         *
         * Requirements:
         *
         * - `spender` cannot be the zero address.
         */
        function approve(address spender, uint256 amount) public returns (bool) {
            _approve(msg.sender, spender, amount);
            return true;
        }
    
        /**
         * @dev See {IERC20-transferFrom}.
         *
         * Emits an {Approval} event indicating the updated allowance. This is not
         * required by the EIP. See the note at the beginning of {ERC20};
         *
         * Requirements:
         * - `sender` and `recipient` cannot be the zero address.
         * - `sender` must have a balance of at least `amount`.
         * - the caller must have allowance for `sender`'s tokens of at least
         * `amount`.
         */
        function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
            _transfer(sender, recipient, amount);
            _approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount, "ERC20: transfer amount exceeds allowance"));
            return true;
        }
    
        /**
         * @dev Atomically increases the allowance granted to `spender` by the caller.
         *
         * This is an alternative to {approve} that can be used as a mitigation for
         * problems described in {IERC20-approve}.
         *
         * Emits an {Approval} event indicating the updated allowance.
         *
         * Requirements:
         *
         * - `spender` cannot be the zero address.
         */
        function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
            _approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue));
            return true;
        }
    
        /**
         * @dev Atomically decreases the allowance granted to `spender` by the caller.
         *
         * This is an alternative to {approve} that can be used as a mitigation for
         * problems described in {IERC20-approve}.
         *
         * Emits an {Approval} event indicating the updated allowance.
         *
         * Requirements:
         *
         * - `spender` cannot be the zero address.
         * - `spender` must have allowance for the caller of at least
         * `subtractedValue`.
         */
        function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
            _approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
            return true;
        }
    
        /**
         * @dev Moves tokens `amount` from `sender` to `recipient`.
         *
         * This is internal function is equivalent to {transfer}, and can be used to
         * e.g. implement automatic token fees, slashing mechanisms, etc.
         *
         * Emits a {Transfer} event.
         *
         * Requirements:
         *
         * - `sender` cannot be the zero address.
         * - `recipient` cannot be the zero address.
         * - `sender` must have a balance of at least `amount`.
         */
        function _transfer(address sender, address recipient, uint256 amount) internal {
            require(sender != address(0), "ERC20: transfer from the zero address");
            require(recipient != address(0), "ERC20: transfer to the zero address");
    
            _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
            _balances[recipient] = _balances[recipient].add(amount);
            emit Transfer(sender, recipient, amount);
        }
    
        /** @dev Creates `amount` tokens and assigns them to `account`, increasing
         * the total supply.
         *
         * Emits a {Transfer} event with `from` set to the zero address.
         *
         * Requirements
         *
         * - `to` cannot be the zero address.
         */
        function _mint(address account, uint256 amount) internal {
            require(account != address(0), "ERC20: mint to the zero address");
    
            _totalSupply = _totalSupply.add(amount);
            _balances[account] = _balances[account].add(amount);
            emit Transfer(address(0), account, amount);
        }
    
        /**
         * @dev Destroys `amount` tokens from `account`, reducing the
         * total supply.
         *
         * Emits a {Transfer} event with `to` set to the zero address.
         *
         * Requirements
         *
         * - `account` cannot be the zero address.
         * - `account` must have at least `amount` tokens.
         */
        function _burn(address account, uint256 amount) internal {
            require(account != address(0), "ERC20: burn from the zero address");
    
            _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
            _totalSupply = _totalSupply.sub(amount);
            emit Transfer(account, address(0), amount);
        }
    
        /**
         * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.
         *
         * This is internal function is equivalent to `approve`, and can be used to
         * e.g. set automatic allowances for certain subsystems, etc.
         *
         * Emits an {Approval} event.
         *
         * Requirements:
         *
         * - `owner` cannot be the zero address.
         * - `spender` cannot be the zero address.
         */
        function _approve(address owner, address spender, uint256 amount) internal {
            require(owner != address(0), "ERC20: approve from the zero address");
            require(spender != address(0), "ERC20: approve to the zero address");
    
            _allowances[owner][spender] = amount;
            emit Approval(owner, spender, amount);
        }
    
        /**
         * @dev Destroys `amount` tokens from `account`.`amount` is then deducted
         * from the caller's allowance.
         *
         * See {_burn} and {_approve}.
         */
        function _burnFrom(address account, uint256 amount) internal {
            _burn(account, amount);
            _approve(account, msg.sender, _allowances[account][msg.sender].sub(amount, "ERC20: burn amount exceeds allowance"));
        }
    
        uint256[50] private ______gap;
    }
    
    // File: contracts\token\ERC20\ERC20Snapshot.sol
    
    pragma solidity ^0.5.16;
    
    
    
    
    
    
    
    /**
     * @dev This contract extends an ERC20 token with a snapshot mechanism. When a snapshot is created, the balances and
     * total supply at the time are recorded for later access.
     *
     * This can be used to safely create mechanisms based on token balances such as trustless dividends or weighted voting.
     * In naive implementations it's possible to perform a "double spend" attack by reusing the same balance from different
     * accounts. By using snapshots to calculate dividends or voting power, those attacks no longer apply. It can also be
     * used to create an efficient ERC20 forking mechanism.
     *
     * Snapshots are created by the internal {_snapshot} function, which will emit the {Snapshot} event and return a
     * snapshot id. To get the total supply at the time of a snapshot, call the function {totalSupplyAt} with the snapshot
     * id. To get the balance of an account at the time of a snapshot, call the {balanceOfAt} function with the snapshot id
     * and the account address.
     *
     * ==== Gas Costs
     *
     * Snapshots are efficient. Snapshot creation is _O(1)_. Retrieval of balances or total supply from a snapshot is _O(log
     * n)_ in the number of snapshots that have been created, although _n_ for a specific account will generally be much
     * smaller since identical balances in subsequent snapshots are stored as a single entry.
     *
     * There is a constant overhead for normal ERC20 transfers due to the additional snapshot bookkeeping. This overhead is
     * only significant for the first transfer that immediately follows a snapshot for a particular account. Subsequent
     * transfers will have normal cost until the next snapshot, and so on.
     */
    contract ERC20Snapshot is Initializable, ERC20 {
    
        using SafeMath for uint256;
        using Arrays for uint256[];
        using Counters for Counters.Counter;
    
        // Snapshotted values have arrays of ids and the value corresponding to that id. These could be an array of a
        // Snapshot struct, but that would impede usage of functions that work on an array.
        struct Snapshots {
            uint256[] ids;
            uint256[] values;
        }
    
        mapping (address => Snapshots) private _accountBalanceSnapshots;
        Snapshots private _totalSupplySnapshots;
    
        // Snapshot ids increase monotonically, with the first value being 1. An id of 0 is invalid.
        Counters.Counter private _currentSnapshotId;
    
        /**
         * @dev Emitted by {_snapshot} when a snapshot identified by `id` is created.
         */
        event Snapshot(uint256 id);
    
        /**
         * @dev Creates a new snapshot and returns its snapshot id.
         *
         * Emits a {Snapshot} event that contains the same id.
         *
         * {_snapshot} is `internal` and you have to decide how to expose it externally. Its usage may be restricted to a
         * set of accounts, for example using {AccessControl}, or it may be open to the public.
         *
         * [WARNING]
         * ====
         * While an open way of calling {_snapshot} is required for certain trust minimization mechanisms such as forking,
         * you must consider that it can potentially be used by attackers in two ways.
         *
         * First, it can be used to increase the cost of retrieval of values from snapshots, although it will grow
         * logarithmically thus rendering this attack ineffective in the long term. Second, it can be used to target
         * specific accounts and increase the cost of ERC20 transfers for them, in the ways specified in the Gas Costs
         * section above.
         *
         * We haven't measured the actual numbers; if this is something you're interested in please reach out to us.
         * ====
         */
        function _snapshot() internal returns (uint256) {
            _currentSnapshotId.increment();
    
            uint256 currentId = _currentSnapshotId.current();
            emit Snapshot(currentId);
            return currentId;
        }
    
        /**
         * @dev Retrieves the balance of `account` at the time `snapshotId` was created.
         */
        function balanceOfAt(address account, uint256 snapshotId) public view returns (uint256) {
            (bool snapshotted, uint256 value) = _valueAt(snapshotId, _accountBalanceSnapshots[account]);
    
            return snapshotted ? value : balanceOf(account);
        }
    
        /**
         * @dev Retrieves the total supply at the time `snapshotId` was created.
         */
        function totalSupplyAt(uint256 snapshotId) public view returns(uint256) {
            (bool snapshotted, uint256 value) = _valueAt(snapshotId, _totalSupplySnapshots);
    
            return snapshotted ? value : totalSupply();
        }
    
        // _transfer, _mint and _burn are the only functions where the balances are modified, so it is there that the
        // snapshots are updated. Note that the update happens _before_ the balance change, with the pre-modified value.
        // The same is true for the total supply and _mint and _burn.
        function _transfer(address from, address to, uint256 value) internal {
            _updateAccountSnapshot(from);
            _updateAccountSnapshot(to);
    
            super._transfer(from, to, value);
        }
    
        function _mint(address account, uint256 value) internal {
            _updateAccountSnapshot(account);
            _updateTotalSupplySnapshot();
    
            super._mint(account, value);
        }
    
        function _burn(address account, uint256 value) internal {
            _updateAccountSnapshot(account);
            _updateTotalSupplySnapshot();
    
            super._burn(account, value);
        }
    
        function _valueAt(uint256 snapshotId, Snapshots storage snapshots)
            private view returns (bool, uint256)
        {
            require(snapshotId > 0, "ERC20Snapshot: id is 0");
            // solhint-disable-next-line max-line-length
            require(snapshotId <= _currentSnapshotId.current(), "ERC20Snapshot: nonexistent id");
    
            // When a valid snapshot is queried, there are three possibilities:
            //  a) The queried value was not modified after the snapshot was taken. Therefore, a snapshot entry was never
            //  created for this id, and all stored snapshot ids are smaller than the requested one. The value that corresponds
            //  to this id is the current one.
            //  b) The queried value was modified after the snapshot was taken. Therefore, there will be an entry with the
            //  requested id, and its value is the one to return.
            //  c) More snapshots were created after the requested one, and the queried value was later modified. There will be
            //  no entry for the requested id: the value that corresponds to it is that of the smallest snapshot id that is
            //  larger than the requested one.
            //
            // In summary, we need to find an element in an array, returning the index of the smallest value that is larger if
            // it is not found, unless said value doesn't exist (e.g. when all values are smaller). Arrays.findUpperBound does
            // exactly this.
    
            uint256 index = snapshots.ids.findUpperBound(snapshotId);
    
            if (index == snapshots.ids.length) {
                return (false, 0);
            } else {
                return (true, snapshots.values[index]);
            }
        }
    
        function _updateAccountSnapshot(address account) private {
            _updateSnapshot(_accountBalanceSnapshots[account], balanceOf(account));
        }
    
        function _updateTotalSupplySnapshot() private {
            _updateSnapshot(_totalSupplySnapshots, totalSupply());
        }
    
        function _updateSnapshot(Snapshots storage snapshots, uint256 currentValue) private {
            uint256 currentId = _currentSnapshotId.current();
            if (_lastSnapshotId(snapshots.ids) < currentId) {
                snapshots.ids.push(currentId);
                snapshots.values.push(currentValue);
            }
        }
    
        function _lastSnapshotId(uint256[] storage ids) private view returns (uint256) {
            if (ids.length == 0) {
                return 0;
            } else {
                return ids[ids.length - 1];
            }
        }
    }
    
    // File: contracts\upgradable\OwnableUpgradable.sol
    
    pragma solidity ^0.5.16;
    
    // import "../openzeppelin/upgrades/contracts/Initializable.sol";
    
    
    contract OwnableUpgradable is Initializable {
        address payable public owner;
        address payable internal newOwnerCandidate;
    
    
        modifier onlyOwner {
            require(msg.sender == owner, "Permission denied");
            _;
        }
    
    
        // ** INITIALIZERS – Constructors for Upgradable contracts **
    
        function initialize() public initializer {
            owner = msg.sender;
        }
    
        function initialize(address payable newOwner) public initializer {
            owner = newOwner;
        }
    
    
        function changeOwner(address payable newOwner) public onlyOwner {
            newOwnerCandidate = newOwner;
        }
    
        function acceptOwner() public {
            require(msg.sender == newOwnerCandidate, "Permission denied");
            owner = newOwnerCandidate;
        }
    
    
        uint256[50] private ______gap;
    }
    
    // File: contracts\deposits\DfDepositToken.sol
    
    pragma solidity ^0.5.16;
    
    
    
    
    
    
    contract DfDepositToken is
        Initializable,
        ERC20Detailed,
        ERC20Snapshot,
        OwnableUpgradable
    {
    
        // ** INITIALIZER **
    
        function initialize(
            string memory _name,
            string memory _symbol,
            uint8 _decimals,
            address payable _controller
        ) public initializer {
            // Initialize Parents Contracts
            ERC20Detailed.initialize(_name, _symbol, _decimals);
            OwnableUpgradable.initialize(_controller);
        }
    
    
        // ** PUBLIC functions **
    
        // Transfer to array of addresses
        function transfer(address[] memory recipients, uint256[] memory amounts) public returns(bool) {
            require(recipients.length == amounts.length, "Arrays lengths not equal");
    
            // transfer to all addresses
            for (uint i = 0; i < recipients.length; i++) {
                _transfer(msg.sender, recipients[i], amounts[i]);
            }
    
            return true;
        }
    
    
        // ** ONLY_OWNER functions **
    
        function snapshot() public onlyOwner returns(uint256 currentId) {
            currentId = _snapshot();
        }
    
        function mint(address account, uint256 amount) public onlyOwner {
            _mint(account, amount);
        }
    
        function burnFrom(address account, uint256 amount) public onlyOwner {
            _burn(account, amount);
        }
    }