Forkchoice Ethereum Mainnet

Address Contract Partially Verified

Address 0x6704ba24b8640BCcEe6BF2fd276a6a1b8EdF4Ade
Balance 0 ETH
Nonce 1
Code Size 8023 bytes
Indexed Transactions 0 (1 on-chain, 1.3% indexed)
External Etherscan · Sourcify

Contract Bytecode

8023 bytes
0x60606040526004361061012f5763ffffffff60e060020a60003504166304ff7d3f811461013457806315b210821461016c57806318160ddd1461019d5780632e0179b5146101b0578063375b74c3146101ec578063380ba30c1461021b5780633a8343ee1461023357806342966c68146102495780635d5e22cd1461025f57806361e1077d1461028d57806370a08231146102b55780637f555b03146102d457806388d695b2146102e757806389064fd2146103765780639189a59e1461039e578063b7279ca6146103b1578063be23d2911461048b578063cb81fecf146104ad578063cf6e4488146104c0578063dd62ed3e146104d6578063de5007ff146104fb578063dfe0f0ca1461050e578063ea5fbfd514610536578063eb55b2a314610555578063f602c312146105af575b600080fd5b341561013f57600080fd5b61014a6004356105c2565b604051600160a060020a03909216825260208201526040908101905180910390f35b341561017757600080fd5b61018b600160a060020a03600435166105e7565b60405190815260200160405180910390f35b34156101a857600080fd5b61018b6106ac565b34156101bb57600080fd5b6101d8600160a060020a0360043581169060243516604435610709565b604051901515815260200160405180910390f35b34156101f757600080fd5b6101ff6108b4565b604051600160a060020a03909116815260200160405180910390f35b341561022657600080fd5b6102316004356108c3565b005b341561023e57600080fd5b610231600435610b37565b341561025457600080fd5b6101d8600435610be8565b341561026a57600080fd5b6101d8600160a060020a0360043581169060243581169060443516606435610ded565b341561029857600080fd5b6101d8600160a060020a03600435811690602435166044356110dc565b34156102c057600080fd5b61018b600160a060020a0360043516611194565b34156102df57600080fd5b6101ff611203565b34156102f257600080fd5b6101d860046024813581810190830135806020818102016040519081016040528093929190818152602001838360200280828437820191505050505050919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284375094965061121295505050505050565b341561038157600080fd5b6101d8600160a060020a036004358116906024351660443561146e565b34156103a957600080fd5b6101ff611592565b34156103bc57600080fd5b6102316004602481358181019083013580602081810201604051908101604052809392919081815260200183836020028082843782019150505050505091908035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284375094965050509235600160a060020a031692506115a1915050565b341561049657600080fd5b61018b600160a060020a03600435166024356118b8565b34156104b857600080fd5b61018b61198f565b34156104cb57600080fd5b6101ff600435611995565b34156104e157600080fd5b61018b600160a060020a03600435811690602435166119b0565b341561050657600080fd5b61018b611a28565b341561051957600080fd5b6101d8600160a060020a0360043581169060243516604435611a2e565b341561054157600080fd5b6101d8600160a060020a0360043516611c26565b341561056057600080fd5b610231600460248135818101908301358060208181020160405190810160405280939291908181526020018383602002808284375094965050509235600160a060020a03169250611c3b915050565b34156105ba57600080fd5b6101ff611e9a565b60086020526000908152604090208054600190910154600160a060020a039091169082565b6000600160a060020a03821615156105fe57600080fd5b610606611ea9565b905060206040519081016040908152600160a060020a038416825260008381526002602052208151815473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0391909116179055507fd76fc900a7e1a6fcf11d54b7ba943918df6c53a3128140658c389b3da1e997ba813384604051928352600160a060020a039182166020840152166040808301919091526060909101905180910390a1919050565b600454600090600160a060020a03166318160ddd6040518163ffffffff1660e060020a028152600401602060405180830381600087803b15156106ee57600080fd5b5af115156106fb57600080fd5b505050604051805191505090565b6003546000908190819033600160a060020a0390811691161461072b57600080fd5b600160a060020a038516151561074057600080fd5b600454600160a060020a0316635c658165878760405160e060020a63ffffffff8516028152600160a060020a03928316600482015291166024820152604401602060405180830381600087803b151561079857600080fd5b5af115156107a557600080fd5b505050604051805192505050828101818110156107c157600080fd5b600454600160a060020a031663da46098c87878460405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401600060405180830381600087803b151561082457600080fd5b5af1151561083157600080fd5b5050600354600160a060020a03169050635687f2b887878460405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401600060405180830381600087803b151561089857600080fd5b5af115156108a557600080fd5b50600198975050505050505050565b600154600160a060020a031681565b600154600090819081908190819033600160a060020a039081169116146108e957600080fd5b60008681526008602052604090208054909550600160a060020a0316935083151561091357600080fd5b600180860154600088815260086020526040808220805473ffffffffffffffffffffffffffffffffffffffff1916815590930155600454909450600160a060020a0316906318160ddd90518163ffffffff1660e060020a028152600401602060405180830381600087803b151561098957600080fd5b5af1151561099657600080fd5b505050604051805192505050818101818110610b2f57600454600160a060020a031663f7ea7a3d8260405160e060020a63ffffffff84160281526004810191909152602401600060405180830381600087803b15156109f457600080fd5b5af11515610a0157600080fd5b5050600454600160a060020a031690506321e5383a858560405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b1515610a5b57600080fd5b5af11515610a6857600080fd5b5050507f1445852a2ef41b86fd81f90a02261a68635ceb02cdbc73f9c5f690af8288f360868585604051928352600160a060020a0390911660208301526040808301919091526060909101905180910390a1600354600160a060020a03166323de66516000868660405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401600060405180830381600087803b1515610b1e57600080fd5b5af11515610b2b57600080fd5b5050505b505050505050565b60015433600160a060020a03908116911614610b5257600080fd5b610b5b81611ef7565b60018054600160a060020a0392831673ffffffffffffffffffffffffffffffffffffffff1991821617825560008481526002602052604090819020805490921690915590547f9a99272c0f6b7a30ef9e76e684a7cd408bfd4f11a72f36a8e276253c920e442d92849291169051918252600160a060020a031660208201526040908101905180910390a150565b6004546000908190600160a060020a03166327e235e33360405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b1515610c3d57600080fd5b5af11515610c4a57600080fd5b505050604051805191505080831115610c6257600080fd5b600454600160a060020a031663e30443bc3385840360405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b1515610cba57600080fd5b5af11515610cc757600080fd5b5050600454600160a060020a0316905063f7ea7a3d84826318160ddd6040518163ffffffff1660e060020a028152600401602060405180830381600087803b1515610d1157600080fd5b5af11515610d1e57600080fd5b505050604051805190500360405160e060020a63ffffffff84160281526004810191909152602401600060405180830381600087803b1515610d5f57600080fd5b5af11515610d6c57600080fd5b5050600354600160a060020a031690506323de66513360008660405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401600060405180830381600087803b1515610dd457600080fd5b5af11515610de157600080fd5b50600195945050505050565b6003546000908190819033600160a060020a03908116911614610e0f57600080fd5b600160a060020a0385161515610e2457600080fd5b600454600160a060020a03166327e235e38760405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b1515610e7457600080fd5b5af11515610e8157600080fd5b505050604051805192505081841115610e9957600080fd5b600454600160a060020a0316635c658165878960405160e060020a63ffffffff8516028152600160a060020a03928316600482015291166024820152604401602060405180830381600087803b1515610ef157600080fd5b5af11515610efe57600080fd5b505050604051805191505080841115610f1657600080fd5b600454600160a060020a031663e30443bc8786850360405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b1515610f6e57600080fd5b5af11515610f7b57600080fd5b5050600454600160a060020a031690506321e5383a868660405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b1515610fd557600080fd5b5af11515610fe257600080fd5b5050600454600160a060020a0316905063da46098c878987850360405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401600060405180830381600087803b151561104b57600080fd5b5af1151561105857600080fd5b5050600354600160a060020a031690506323de665187878760405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401600060405180830381600087803b15156110bf57600080fd5b5af115156110cc57600080fd5b5060019998505050505050505050565b6003546000908190819033600160a060020a039081169116146110fe57600080fd5b600160a060020a038516151561111357600080fd5b600454600160a060020a0316635c658165878760405160e060020a63ffffffff8516028152600160a060020a03928316600482015291166024820152604401602060405180830381600087803b151561116b57600080fd5b5af1151561117857600080fd5b505050604051805192505050828103818111156107c157600080fd5b600454600090600160a060020a03166327e235e38360405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b15156111e757600080fd5b5af115156111f457600080fd5b50505060405180519392505050565b600354600160a060020a031681565b600080600080600080865188511461122957600080fd5b8751600454909550600160a060020a03166327e235e33360405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b151561127e57600080fd5b5af1151561128b57600080fd5b5050506040518051945060009350505b848310156113fa578783815181106112af57fe5b906020019060200201519150600160a060020a03821615156112d057600080fd5b8683815181106112dc57fe5b906020019060200201519050808410156112f557600080fd5b81600160a060020a031633600160a060020a031614151561137c576004549381900393600160a060020a03166321e5383a838360405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b151561136b57600080fd5b5af1151561137857600080fd5b5050505b600354600160a060020a03166323de665133848460405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401600060405180830381600087803b15156113df57600080fd5b5af115156113ec57600080fd5b50506001909301925061129b565b600454600160a060020a031663e30443bc338660405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b151561145057600080fd5b5af1151561145d57600080fd5b5060019a9950505050505050505050565b60035460009033600160a060020a0390811691161461148c57600080fd5b600160a060020a03831615156114a157600080fd5b600454600160a060020a031663da46098c85858560405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401600060405180830381600087803b151561150457600080fd5b5af1151561151157600080fd5b5050600354600160a060020a03169050635687f2b885858560405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401600060405180830381600087803b151561157857600080fd5b5af1151561158557600080fd5b5060019695505050505050565b600554600160a060020a031681565b600554600090819081908190819033600160a060020a039081169116146115c757600080fd5b600160a060020a03861615156115dc57600080fd5b875189511480156115ee575086518951145b15156115f957600080fd5b8851945060009350600092505b8483101561183e5760016006548a858151811061161f57fe5b906020019060200201518a868151811061163557fe5b906020019060200201518a878151811061164b57fe5b906020019060200201516040516000815260200160405260405193845260ff9092166020808501919091526040808501929092526060840192909252608090920191516020810390808403906000865af115156116a757600080fd5b5050602060405103519150600160a060020a0382161561183357600160a060020a0380831660009081526007602052604090819020805460ff19166001179055600454909116906327e235e39084905160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b151561173257600080fd5b5af1151561173f57600080fd5b505050604051805191505060008111156118335760045493810193600160a060020a031663e30443bc83600060405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b15156117ae57600080fd5b5af115156117bb57600080fd5b5050600354600160a060020a031690506323de665183888460405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401600060405180830381600087803b151561182257600080fd5b5af1151561182f57600080fd5b5050505b826001019250611606565b6000841115610b2b57600454600160a060020a03166321e5383a878660405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b151561189d57600080fd5b5af115156118aa57600080fd5b505050505050505050505050565b6000600160a060020a03831615156118cf57600080fd5b6118d7611ea9565b9050604080519081016040908152600160a060020a0385168252602080830185905260008481526008909152208151815473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a03919091161781556020820151600190910155507f021724c3943709b5b29b9cdcfb21e18e7355b036e07d869b4a69bd8a13ec45e8818484604051928352600160a060020a0390911660208301526040808301919091526060909101905180910390a192915050565b60005481565b600260205260009081526040902054600160a060020a031681565b600454600090600160a060020a0316635c658165848460405160e060020a63ffffffff8516028152600160a060020a03928316600482015291166024820152604401602060405180830381600087803b1515611a0b57600080fd5b5af11515611a1857600080fd5b5050506040518051949350505050565b60065481565b600354600090819033600160a060020a03908116911614611a4e57600080fd5b600160a060020a0384161515611a6357600080fd5b600454600160a060020a03166327e235e38660405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b1515611ab357600080fd5b5af11515611ac057600080fd5b505050604051805191505080831115611ad857600080fd5b600454600160a060020a031663e30443bc8685840360405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b1515611b3057600080fd5b5af11515611b3d57600080fd5b5050600454600160a060020a031690506321e5383a858560405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b1515611b9757600080fd5b5af11515611ba457600080fd5b5050600354600160a060020a031690506323de665186868660405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401600060405180830381600087803b1515611c0b57600080fd5b5af11515611c1857600080fd5b506001979650505050505050565b60076020526000908152604090205460ff1681565b600554600090819081908190819033600160a060020a03908116911614611c6157600080fd5b600160a060020a0386161515611c7657600080fd5b8651945060009350600092505b84831015611e2157868381518110611c9757fe5b90602001906020020151600160a060020a03811660009081526007602052604090205490925060ff1615611e1657600454600160a060020a03166327e235e38360405160e060020a63ffffffff8416028152600160a060020a039091166004820152602401602060405180830381600087803b1515611d1557600080fd5b5af11515611d2257600080fd5b50505060405180519150506000811115611e165760045493810193600160a060020a031663e30443bc83600060405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b1515611d9157600080fd5b5af11515611d9e57600080fd5b5050600354600160a060020a031690506323de665183888460405160e060020a63ffffffff8616028152600160a060020a0393841660048201529190921660248201526044810191909152606401600060405180830381600087803b1515611e0557600080fd5b5af11515611e1257600080fd5b5050505b826001019250611c83565b6000841115611e9157600454600160a060020a03166321e5383a878660405160e060020a63ffffffff8516028152600160a060020a0390921660048301526024820152604401600060405180830381600087803b1515611e8057600080fd5b5af11515611e8d57600080fd5b5050505b50505050505050565b600454600160a060020a031681565b60008054600101808255600019430140903090604051928352600160a060020a03919091166c0100000000000000000000000002602083015260348201526054016040518091039020905090565b60008181526002602052604081208054600160a060020a03161515611f1b57600080fd5b54600160a060020a0316929150505600a165627a7a72305820bb3d79ad80497ce403b23be2406a462aecf8911032b9bc5d433691332b9b2e810029

Verified Source Code Partial Match

Compiler: v0.4.21+commit.dfe3193c EVM: byzantium Optimization: Yes (200 runs)
ERC20Impl.sol 1028 lines
pragma solidity ^0.4.21;

/** @title  A contract for generating unique identifiers
  *
  * @notice  A contract that provides a identifier generation scheme,
  * guaranteeing uniqueness across all contracts that inherit from it,
  * as well as unpredictability of future identifiers.
  *
  * @dev  This contract is intended to be inherited by any contract that
  * implements the callback software pattern for cooperative custodianship.
  *
  * @author  Gemini Trust Company, LLC
  */
contract LockRequestable {

    // MEMBERS
    /// @notice  the count of all invocations of `generateLockId`.
    uint256 public lockRequestCount;

    // CONSTRUCTOR
    function LockRequestable() public {
        lockRequestCount = 0;
    }

    // FUNCTIONS
    /** @notice  Returns a fresh unique identifier.
      *
      * @dev the generation scheme uses three components.
      * First, the blockhash of the previous block.
      * Second, the deployed address.
      * Third, the next value of the counter.
      * This ensure that identifiers are unique across all contracts
      * following this scheme, and that future identifiers are
      * unpredictable.
      *
      * @return a 32-byte unique identifier.
      */
    function generateLockId() internal returns (bytes32 lockId) {
        return keccak256(block.blockhash(block.number - 1), address(this), ++lockRequestCount);
    }
}


/** @title  A contract to inherit upgradeable custodianship.
  *
  * @notice  A contract that provides re-usable code for upgradeable
  * custodianship. That custodian may be an account or another contract.
  *
  * @dev  This contract is intended to be inherited by any contract
  * requiring a custodian to control some aspect of its functionality.
  * This contract provides the mechanism for that custodianship to be
  * passed from one custodian to the next.
  *
  * @author  Gemini Trust Company, LLC
  */
contract CustodianUpgradeable is LockRequestable {

    // TYPES
    /// @dev  The struct type for pending custodian changes.
    struct CustodianChangeRequest {
        address proposedNew;
    }

    // MEMBERS
    /// @dev  The address of the account or contract that acts as the custodian.
    address public custodian;

    /// @dev  The map of lock ids to pending custodian changes.
    mapping (bytes32 => CustodianChangeRequest) public custodianChangeReqs;

    // CONSTRUCTOR
    function CustodianUpgradeable(
        address _custodian
    )
      LockRequestable()
      public
    {
        custodian = _custodian;
    }

    // MODIFIERS
    modifier onlyCustodian {
        require(msg.sender == custodian);
        _;
    }

    // PUBLIC FUNCTIONS
    // (UPGRADE)

    /** @notice  Requests a change of the custodian associated with this contract.
      *
      * @dev  Returns a unique lock id associated with the request.
      * Anyone can call this function, but confirming the request is authorized
      * by the custodian.
      *
      * @param  _proposedCustodian  The address of the new custodian.
      * @return  lockId  A unique identifier for this request.
      */
    function requestCustodianChange(address _proposedCustodian) public returns (bytes32 lockId) {
        require(_proposedCustodian != address(0));

        lockId = generateLockId();

        custodianChangeReqs[lockId] = CustodianChangeRequest({
            proposedNew: _proposedCustodian
        });

        emit CustodianChangeRequested(lockId, msg.sender, _proposedCustodian);
    }

    /** @notice  Confirms a pending change of the custodian associated with this contract.
      *
      * @dev  When called by the current custodian with a lock id associated with a
      * pending custodian change, the `address custodian` member will be updated with the
      * requested address.
      *
      * @param  _lockId  The identifier of a pending change request.
      */
    function confirmCustodianChange(bytes32 _lockId) public onlyCustodian {
        custodian = getCustodianChangeReq(_lockId);

        delete custodianChangeReqs[_lockId];

        emit CustodianChangeConfirmed(_lockId, custodian);
    }

    // PRIVATE FUNCTIONS
    function getCustodianChangeReq(bytes32 _lockId) private view returns (address _proposedNew) {
        CustodianChangeRequest storage changeRequest = custodianChangeReqs[_lockId];

        // reject ‘null’ results from the map lookup
        // this can only be the case if an unknown `_lockId` is received
        require(changeRequest.proposedNew != 0);

        return changeRequest.proposedNew;
    }

    /// @dev  Emitted by successful `requestCustodianChange` calls.
    event CustodianChangeRequested(
        bytes32 _lockId,
        address _msgSender,
        address _proposedCustodian
    );

    /// @dev Emitted by successful `confirmCustodianChange` calls.
    event CustodianChangeConfirmed(bytes32 _lockId, address _newCustodian);
}


/** @title  A contract to inherit upgradeable token implementations.
  *
  * @notice  A contract that provides re-usable code for upgradeable
  * token implementations. It itself inherits from `CustodianUpgradable`
  * as the upgrade process is controlled by the custodian.
  *
  * @dev  This contract is intended to be inherited by any contract
  * requiring a reference to the active token implementation, either
  * to delegate calls to it, or authorize calls from it. This contract
  * provides the mechanism for that implementation to be be replaced,
  * which constitutes an implementation upgrade.
  *
  * @author Gemini Trust Company, LLC
  */
contract ERC20ImplUpgradeable is CustodianUpgradeable  {

    // TYPES
    /// @dev  The struct type for pending implementation changes.
    struct ImplChangeRequest {
        address proposedNew;
    }

    // MEMBERS
    // @dev  The reference to the active token implementation.
    ERC20Impl public erc20Impl;

    /// @dev  The map of lock ids to pending implementation changes.
    mapping (bytes32 => ImplChangeRequest) public implChangeReqs;

    // CONSTRUCTOR
    function ERC20ImplUpgradeable(address _custodian) CustodianUpgradeable(_custodian) public {
        erc20Impl = ERC20Impl(0x0);
    }

    // MODIFIERS
    modifier onlyImpl {
        require(msg.sender == address(erc20Impl));
        _;
    }

    // PUBLIC FUNCTIONS
    // (UPGRADE)
    /** @notice  Requests a change of the active implementation associated
      * with this contract.
      *
      * @dev  Returns a unique lock id associated with the request.
      * Anyone can call this function, but confirming the request is authorized
      * by the custodian.
      *
      * @param  _proposedImpl  The address of the new active implementation.
      * @return  lockId  A unique identifier for this request.
      */
    function requestImplChange(address _proposedImpl) public returns (bytes32 lockId) {
        require(_proposedImpl != address(0));

        lockId = generateLockId();

        implChangeReqs[lockId] = ImplChangeRequest({
            proposedNew: _proposedImpl
        });

        emit ImplChangeRequested(lockId, msg.sender, _proposedImpl);
    }

    /** @notice  Confirms a pending change of the active implementation
      * associated with this contract.
      *
      * @dev  When called by the custodian with a lock id associated with a
      * pending change, the `ERC20Impl erc20Impl` member will be updated
      * with the requested address.
      *
      * @param  _lockId  The identifier of a pending change request.
      */
    function confirmImplChange(bytes32 _lockId) public onlyCustodian {
        erc20Impl = getImplChangeReq(_lockId);

        delete implChangeReqs[_lockId];

        emit ImplChangeConfirmed(_lockId, address(erc20Impl));
    }

    // PRIVATE FUNCTIONS
    function getImplChangeReq(bytes32 _lockId) private view returns (ERC20Impl _proposedNew) {
        ImplChangeRequest storage changeRequest = implChangeReqs[_lockId];

        // reject ‘null’ results from the map lookup
        // this can only be the case if an unknown `_lockId` is received
        require(changeRequest.proposedNew != address(0));

        return ERC20Impl(changeRequest.proposedNew);
    }

    /// @dev  Emitted by successful `requestImplChange` calls.
    event ImplChangeRequested(
        bytes32 _lockId,
        address _msgSender,
        address _proposedImpl
    );

    /// @dev Emitted by successful `confirmImplChange` calls.
    event ImplChangeConfirmed(bytes32 _lockId, address _newImpl);
}


contract ERC20Interface {
  // METHODS

  // NOTE:
  //   public getter functions are not currently recognised as an
  //   implementation of the matching abstract function by the compiler.

  // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md#name
  // function name() public view returns (string);

  // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md#symbol
  // function symbol() public view returns (string);

  // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md#totalsupply
  // function decimals() public view returns (uint8);

  // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md#totalsupply
  function totalSupply() public view returns (uint256);

  // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md#balanceof
  function balanceOf(address _owner) public view returns (uint256 balance);

  // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md#transfer
  function transfer(address _to, uint256 _value) public returns (bool success);

  // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md#transferfrom
  function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);

  // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md#approve
  function approve(address _spender, uint256 _value) public returns (bool success);

  // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md#allowance
  function allowance(address _owner, address _spender) public view returns (uint256 remaining);

  // EVENTS
  // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md#transfer-1
  event Transfer(address indexed _from, address indexed _to, uint256 _value);

  // https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md#approval
  event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}


/** @title  Public interface to ERC20 compliant token.
  *
  * @notice  This contract is a permanent entry point to an ERC20 compliant
  * system of contracts.
  *
  * @dev  This contract contains no business logic and instead
  * delegates to an instance of ERC20Impl. This contract also has no storage
  * that constitutes the operational state of the token. This contract is
  * upgradeable in the sense that the `custodian` can update the
  * `erc20Impl` address, thus redirecting the delegation of business logic.
  * The `custodian` is also authorized to pass custodianship.
  *
  * @author  Gemini Trust Company, LLC
  */
contract ERC20Proxy is ERC20Interface, ERC20ImplUpgradeable {

    // MEMBERS
    /// @notice  Returns the name of the token.
    string public name;

    /// @notice  Returns the symbol of the token.
    string public symbol;

    /// @notice  Returns the number of decimals the token uses.
    uint8 public decimals;

    // CONSTRUCTOR
    function ERC20Proxy(
        string _name,
        string _symbol,
        uint8 _decimals,
        address _custodian
    )
        ERC20ImplUpgradeable(_custodian)
        public
    {
        name = _name;
        symbol = _symbol;
        decimals = _decimals;
    }

    // PUBLIC FUNCTIONS
    // (ERC20Interface)
    /** @notice  Returns the total token supply.
      *
      * @return  the total token supply.
      */
    function totalSupply() public view returns (uint256) {
        return erc20Impl.totalSupply();
    }

    /** @notice  Returns the account balance of another account with address
      * `_owner`.
      *
      * @return  balance  the balance of account with address `_owner`.
      */
    function balanceOf(address _owner) public view returns (uint256 balance) {
        return erc20Impl.balanceOf(_owner);
    }

    /** @dev Internal use only.
      */
    function emitTransfer(address _from, address _to, uint256 _value) public onlyImpl {
        emit Transfer(_from, _to, _value);
    }

    /** @notice  Transfers `_value` amount of tokens to address `_to`.
      *
      * @dev Will fire the `Transfer` event. Will revert if the `_from`
      * account balance does not have enough tokens to spend.
      *
      * @return  success  true if transfer completes.
      */
    function transfer(address _to, uint256 _value) public returns (bool success) {
        return erc20Impl.transferWithSender(msg.sender, _to, _value);
    }

    /** @notice  Transfers `_value` amount of tokens from address `_from`
      * to address `_to`.
      *
      * @dev  Will fire the `Transfer` event. Will revert unless the `_from`
      * account has deliberately authorized the sender of the message
      * via some mechanism.
      *
      * @return  success  true if transfer completes.
      */
    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
        return erc20Impl.transferFromWithSender(msg.sender, _from, _to, _value);
    }

    /** @dev Internal use only.
      */
    function emitApproval(address _owner, address _spender, uint256 _value) public onlyImpl {
        emit Approval(_owner, _spender, _value);
    }

    /** @notice  Allows `_spender` to withdraw from your account multiple times,
      * up to the `_value` amount. If this function is called again it
      * overwrites the current allowance with _value.
      *
      * @dev  Will fire the `Approval` event.
      *
      * @return  success  true if approval completes.
      */
    function approve(address _spender, uint256 _value) public returns (bool success) {
        return erc20Impl.approveWithSender(msg.sender, _spender, _value);
    }

    /** @notice Increases the amount `_spender` is allowed to withdraw from
      * your account.
      * This function is implemented to avoid the race condition in standard
      * ERC20 contracts surrounding the `approve` method.
      *
      * @dev  Will fire the `Approval` event. This function should be used instead of
      * `approve`.
      *
      * @return  success  true if approval completes.
      */
    function increaseApproval(address _spender, uint256 _addedValue) public returns (bool success) {
        return erc20Impl.increaseApprovalWithSender(msg.sender, _spender, _addedValue);
    }

    /** @notice  Decreases the amount `_spender` is allowed to withdraw from
      * your account. This function is implemented to avoid the race
      * condition in standard ERC20 contracts surrounding the `approve` method.
      *
      * @dev  Will fire the `Approval` event. This function should be used
      * instead of `approve`.
      *
      * @return  success  true if approval completes.
      */
    function decreaseApproval(address _spender, uint256 _subtractedValue) public returns (bool success) {
        return erc20Impl.decreaseApprovalWithSender(msg.sender, _spender, _subtractedValue);
    }

    /** @notice  Returns how much `_spender` is currently allowed to spend from
      * `_owner`'s balance.
      *
      * @return  remaining  the remaining allowance.
      */
    function allowance(address _owner, address _spender) public view returns (uint256 remaining) {
        return erc20Impl.allowance(_owner, _spender);
    }
}


/** @title  ERC20 compliant token intermediary contract holding core logic.
  *
  * @notice  This contract serves as an intermediary between the exposed ERC20
  * interface in ERC20Proxy and the store of balances in ERC20Store. This
  * contract contains core logic that the proxy can delegate to
  * and that the store is called by.
  *
  * @dev  This contract contains the core logic to implement the
  * ERC20 specification as well as several extensions.
  * 1. Changes to the token supply.
  * 2. Batched transfers.
  * 3. Relative changes to spending approvals.
  * 4. Delegated transfer control ('sweeping').
  *
  * @author  Gemini Trust Company, LLC
  */
contract ERC20Impl is CustodianUpgradeable {

    // TYPES
    /// @dev  The struct type for pending increases to the token supply (print).
    struct PendingPrint {
        address receiver;
        uint256 value;
    }

    // MEMBERS
    /// @dev  The reference to the proxy.
    ERC20Proxy public erc20Proxy;

    /// @dev  The reference to the store.
    ERC20Store public erc20Store;

    /// @dev  The sole authorized caller of delegated transfer control ('sweeping').
    address public sweeper;

    /** @dev  The static message to be signed by an external account that
      * signifies their permission to forward their balance to any arbitrary
      * address. This is used to consolidate the control of all accounts
      * backed by a shared keychain into the control of a single key.
      * Initialized as the concatenation of the address of this contract
      * and the word "sweep". This concatenation is done to prevent a replay
      * attack in a subsequent contract, where the sweep message could
      * potentially be replayed to re-enable sweeping ability.
      */
    bytes32 public sweepMsg;

    /** @dev  The mapping that stores whether the address in question has
      * enabled sweeping its contents to another account or not.
      * If an address maps to "true", it has already enabled sweeping,
      * and thus does not need to re-sign the `sweepMsg` to enact the sweep.
      */
    mapping (address => bool) public sweptSet;

    /// @dev  The map of lock ids to pending token increases.
    mapping (bytes32 => PendingPrint) public pendingPrintMap;

    // CONSTRUCTOR
    function ERC20Impl(
          address _erc20Proxy,
          address _erc20Store,
          address _custodian,
          address _sweeper
    )
        CustodianUpgradeable(_custodian)
        public
    {
        require(_sweeper != 0);
        erc20Proxy = ERC20Proxy(_erc20Proxy);
        erc20Store = ERC20Store(_erc20Store);

        sweeper = _sweeper;
        sweepMsg = keccak256(address(this), "sweep");
    }

    // MODIFIERS
    modifier onlyProxy {
        require(msg.sender == address(erc20Proxy));
        _;
    }
    modifier onlySweeper {
        require(msg.sender == sweeper);
        _;
    }


    /** @notice  Core logic of the ERC20 `approve` function.
      *
      * @dev  This function can only be called by the referenced proxy,
      * which has an `approve` function.
      * Every argument passed to that function as well as the original
      * `msg.sender` gets passed to this function.
      * NOTE: approvals for the zero address (unspendable) are disallowed.
      *
      * @param  _sender  The address initiating the approval in proxy.
      */
    function approveWithSender(
        address _sender,
        address _spender,
        uint256 _value
    )
        public
        onlyProxy
        returns (bool success)
    {
        require(_spender != address(0)); // disallow unspendable approvals
        erc20Store.setAllowance(_sender, _spender, _value);
        erc20Proxy.emitApproval(_sender, _spender, _value);
        return true;
    }

    /** @notice  Core logic of the `increaseApproval` function.
      *
      * @dev  This function can only be called by the referenced proxy,
      * which has an `increaseApproval` function.
      * Every argument passed to that function as well as the original
      * `msg.sender` gets passed to this function.
      * NOTE: approvals for the zero address (unspendable) are disallowed.
      *
      * @param  _sender  The address initiating the approval.
      */
    function increaseApprovalWithSender(
        address _sender,
        address _spender,
        uint256 _addedValue
    )
        public
        onlyProxy
        returns (bool success)
    {
        require(_spender != address(0)); // disallow unspendable approvals
        uint256 currentAllowance = erc20Store.allowed(_sender, _spender);
        uint256 newAllowance = currentAllowance + _addedValue;

        require(newAllowance >= currentAllowance);

        erc20Store.setAllowance(_sender, _spender, newAllowance);
        erc20Proxy.emitApproval(_sender, _spender, newAllowance);
        return true;
    }

    /** @notice  Core logic of the `decreaseApproval` function.
      *
      * @dev  This function can only be called by the referenced proxy,
      * which has a `decreaseApproval` function.
      * Every argument passed to that function as well as the original
      * `msg.sender` gets passed to this function.
      * NOTE: approvals for the zero address (unspendable) are disallowed.
      *
      * @param  _sender  The address initiating the approval.
      */
    function decreaseApprovalWithSender(
        address _sender,
        address _spender,
        uint256 _subtractedValue
    )
        public
        onlyProxy
        returns (bool success)
    {
        require(_spender != address(0)); // disallow unspendable approvals
        uint256 currentAllowance = erc20Store.allowed(_sender, _spender);
        uint256 newAllowance = currentAllowance - _subtractedValue;

        require(newAllowance <= currentAllowance);

        erc20Store.setAllowance(_sender, _spender, newAllowance);
        erc20Proxy.emitApproval(_sender, _spender, newAllowance);
        return true;
    }

    /** @notice  Requests an increase in the token supply, with the newly created
      * tokens to be added to the balance of the specified account.
      *
      * @dev  Returns a unique lock id associated with the request.
      * Anyone can call this function, but confirming the request is authorized
      * by the custodian.
      * NOTE: printing to the zero address is disallowed.
      *
      * @param  _receiver  The receiving address of the print, if confirmed.
      * @param  _value  The number of tokens to add to the total supply and the
      * balance of the receiving address, if confirmed.
      *
      * @return  lockId  A unique identifier for this request.
      */
    function requestPrint(address _receiver, uint256 _value) public returns (bytes32 lockId) {
        require(_receiver != address(0));

        lockId = generateLockId();

        pendingPrintMap[lockId] = PendingPrint({
            receiver: _receiver,
            value: _value
        });

        emit PrintingLocked(lockId, _receiver, _value);
    }

    /** @notice  Confirms a pending increase in the token supply.
      *
      * @dev  When called by the custodian with a lock id associated with a
      * pending increase, the amount requested to be printed in the print request
      * is printed to the receiving address specified in that same request.
      * NOTE: this function will not execute any print that would overflow the
      * total supply, but it will not revert either.
      *
      * @param  _lockId  The identifier of a pending print request.
      */
    function confirmPrint(bytes32 _lockId) public onlyCustodian {
        PendingPrint storage print = pendingPrintMap[_lockId];

        // reject ‘null’ results from the map lookup
        // this can only be the case if an unknown `_lockId` is received
        address receiver = print.receiver;
        require (receiver != address(0));
        uint256 value = print.value;

        delete pendingPrintMap[_lockId];

        uint256 supply = erc20Store.totalSupply();
        uint256 newSupply = supply + value;
        if (newSupply >= supply) {
          erc20Store.setTotalSupply(newSupply);
          erc20Store.addBalance(receiver, value);

          emit PrintingConfirmed(_lockId, receiver, value);
          erc20Proxy.emitTransfer(address(0), receiver, value);
        }
    }

    /** @notice  Burns the specified value from the sender's balance.
      *
      * @dev  Sender's balanced is subtracted by the amount they wish to burn.
      *
      * @param  _value  The amount to burn.
      *
      * @return  success  true if the burn succeeded.
      */
    function burn(uint256 _value) public returns (bool success) {
        uint256 balanceOfSender = erc20Store.balances(msg.sender);
        require(_value <= balanceOfSender);

        erc20Store.setBalance(msg.sender, balanceOfSender - _value);
        erc20Store.setTotalSupply(erc20Store.totalSupply() - _value);

        erc20Proxy.emitTransfer(msg.sender, address(0), _value);

        return true;
    }

    /** @notice  A function for a sender to issue multiple transfers to multiple
      * different addresses at once. This function is implemented for gas
      * considerations when someone wishes to transfer, as one transaction is
      * cheaper than issuing several distinct individual `transfer` transactions.
      *
      * @dev  By specifying a set of destination addresses and values, the
      * sender can issue one transaction to transfer multiple amounts to
      * distinct addresses, rather than issuing each as a separate
      * transaction. The `_tos` and `_values` arrays must be equal length, and
      * an index in one array corresponds to the same index in the other array
      * (e.g. `_tos[0]` will receive `_values[0]`, `_tos[1]` will receive
      * `_values[1]`, and so on.)
      * NOTE: transfers to the zero address are disallowed.
      *
      * @param  _tos  The destination addresses to receive the transfers.
      * @param  _values  The values for each destination address.
      * @return  success  If transfers succeeded.
      */
    function batchTransfer(address[] _tos, uint256[] _values) public returns (bool success) {
        require(_tos.length == _values.length);

        uint256 numTransfers = _tos.length;
        uint256 senderBalance = erc20Store.balances(msg.sender);

        for (uint256 i = 0; i < numTransfers; i++) {
          address to = _tos[i];
          require(to != address(0));
          uint256 v = _values[i];
          require(senderBalance >= v);

          if (msg.sender != to) {
            senderBalance -= v;
            erc20Store.addBalance(to, v);
          }
          erc20Proxy.emitTransfer(msg.sender, to, v);
        }

        erc20Store.setBalance(msg.sender, senderBalance);

        return true;
    }

    /** @notice  Enables the delegation of transfer control for many
      * accounts to the sweeper account, transferring any balances
      * as well to the given destination.
      *
      * @dev  An account delegates transfer control by signing the
      * value of `sweepMsg`. The sweeper account is the only authorized
      * caller of this function, so it must relay signatures on behalf
      * of accounts that delegate transfer control to it. Enabling
      * delegation is idempotent and permanent. If the account has a
      * balance at the time of enabling delegation, its balance is
      * also transfered to the given destination account `_to`.
      * NOTE: transfers to the zero address are disallowed.
      *
      * @param  _vs  The array of recovery byte components of the ECDSA signatures.
      * @param  _rs  The array of 'R' components of the ECDSA signatures.
      * @param  _ss  The array of 'S' components of the ECDSA signatures.
      * @param  _to  The destination for swept balances.
      */
    function enableSweep(uint8[] _vs, bytes32[] _rs, bytes32[] _ss, address _to) public onlySweeper {
        require(_to != address(0));
        require((_vs.length == _rs.length) && (_vs.length == _ss.length));

        uint256 numSignatures = _vs.length;
        uint256 sweptBalance = 0;

        for (uint256 i=0; i<numSignatures; ++i) {
          address from = ecrecover(sweepMsg, _vs[i], _rs[i], _ss[i]);

          // ecrecover returns 0 on malformed input
          if (from != address(0)) {
            sweptSet[from] = true;

            uint256 fromBalance = erc20Store.balances(from);

            if (fromBalance > 0) {
              sweptBalance += fromBalance;

              erc20Store.setBalance(from, 0);

              erc20Proxy.emitTransfer(from, _to, fromBalance);
            }
          }
        }

        if (sweptBalance > 0) {
          erc20Store.addBalance(_to, sweptBalance);
        }
    }

    /** @notice  For accounts that have delegated, transfer control
      * to the sweeper, this function transfers their balances to the given
      * destination.
      *
      * @dev The sweeper account is the only authorized caller of
      * this function. This function accepts an array of addresses to have their
      * balances transferred for gas efficiency purposes.
      * NOTE: any address for an account that has not been previously enabled
      * will be ignored.
      * NOTE: transfers to the zero address are disallowed.
      *
      * @param  _froms  The addresses to have their balances swept.
      * @param  _to  The destination address of all these transfers.
      */
    function replaySweep(address[] _froms, address _to) public onlySweeper {
        require(_to != address(0));
        uint256 lenFroms = _froms.length;
        uint256 sweptBalance = 0;

        for (uint256 i=0; i<lenFroms; ++i) {
            address from = _froms[i];

            if (sweptSet[from]) {
                uint256 fromBalance = erc20Store.balances(from);

                if (fromBalance > 0) {
                    sweptBalance += fromBalance;

                    erc20Store.setBalance(from, 0);

                    erc20Proxy.emitTransfer(from, _to, fromBalance);
                }
            }
        }

        if (sweptBalance > 0) {
            erc20Store.addBalance(_to, sweptBalance);
        }
    }

    /** @notice  Core logic of the ERC20 `transferFrom` function.
      *
      * @dev  This function can only be called by the referenced proxy,
      * which has a `transferFrom` function.
      * Every argument passed to that function as well as the original
      * `msg.sender` gets passed to this function.
      * NOTE: transfers to the zero address are disallowed.
      *
      * @param  _sender  The address initiating the transfer in proxy.
      */
    function transferFromWithSender(
        address _sender,
        address _from,
        address _to,
        uint256 _value
    )
        public
        onlyProxy
        returns (bool success)
    {
        require(_to != address(0)); // ensure burn is the cannonical transfer to 0x0

        uint256 balanceOfFrom = erc20Store.balances(_from);
        require(_value <= balanceOfFrom);

        uint256 senderAllowance = erc20Store.allowed(_from, _sender);
        require(_value <= senderAllowance);

        erc20Store.setBalance(_from, balanceOfFrom - _value);
        erc20Store.addBalance(_to, _value);

        erc20Store.setAllowance(_from, _sender, senderAllowance - _value);

        erc20Proxy.emitTransfer(_from, _to, _value);

        return true;
    }

    /** @notice  Core logic of the ERC20 `transfer` function.
      *
      * @dev  This function can only be called by the referenced proxy,
      * which has a `transfer` function.
      * Every argument passed to that function as well as the original
      * `msg.sender` gets passed to this function.
      * NOTE: transfers to the zero address are disallowed.
      *
      * @param  _sender  The address initiating the transfer in proxy.
      */
    function transferWithSender(
        address _sender,
        address _to,
        uint256 _value
    )
        public
        onlyProxy
        returns (bool success)
    {
        require(_to != address(0)); // ensure burn is the cannonical transfer to 0x0

        uint256 balanceOfSender = erc20Store.balances(_sender);
        require(_value <= balanceOfSender);

        erc20Store.setBalance(_sender, balanceOfSender - _value);
        erc20Store.addBalance(_to, _value);

        erc20Proxy.emitTransfer(_sender, _to, _value);

        return true;
    }

    // METHODS (ERC20 sub interface impl.)
    /// @notice  Core logic of the ERC20 `totalSupply` function.
    function totalSupply() public view returns (uint256) {
        return erc20Store.totalSupply();
    }

    /// @notice  Core logic of the ERC20 `balanceOf` function.
    function balanceOf(address _owner) public view returns (uint256 balance) {
        return erc20Store.balances(_owner);
    }

    /// @notice  Core logic of the ERC20 `allowance` function.
    function allowance(address _owner, address _spender) public view returns (uint256 remaining) {
        return erc20Store.allowed(_owner, _spender);
    }

    // EVENTS
    /// @dev  Emitted by successful `requestPrint` calls.
    event PrintingLocked(bytes32 _lockId, address _receiver, uint256 _value);
    /// @dev Emitted by successful `confirmPrint` calls.
    event PrintingConfirmed(bytes32 _lockId, address _receiver, uint256 _value);
}


/** @title  ERC20 compliant token balance store.
  *
  * @notice  This contract serves as the store of balances, allowances, and
  * supply for the ERC20 compliant token. No business logic exists here.
  *
  * @dev  This contract contains no business logic and instead
  * is the final destination for any change in balances, allowances, or token
  * supply. This contract is upgradeable in the sense that its custodian can
  * update the `erc20Impl` address, thus redirecting the source of logic that
  * determines how the balances will be updated.
  *
  * @author  Gemini Trust Company, LLC
  */
contract ERC20Store is ERC20ImplUpgradeable {

    // MEMBERS
    /// @dev  The total token supply.
    uint256 public totalSupply;

    /// @dev  The mapping of balances.
    mapping (address => uint256) public balances;

    /// @dev  The mapping of allowances.
    mapping (address => mapping (address => uint256)) public allowed;

    // CONSTRUCTOR
    function ERC20Store(address _custodian) ERC20ImplUpgradeable(_custodian) public {
        totalSupply = 0;
    }


    // PUBLIC FUNCTIONS
    // (ERC20 Ledger)

    /** @notice  The function to set the total supply of tokens.
      *
      * @dev  Intended for use by token implementation functions
      * that update the total supply. The only authorized caller
      * is the active implementation.
      *
      * @param _newTotalSupply the value to set as the new total supply
      */
    function setTotalSupply(
        uint256 _newTotalSupply
    )
        public
        onlyImpl
    {
        totalSupply = _newTotalSupply;
    }

    /** @notice  Sets how much `_owner` allows `_spender` to transfer on behalf
      * of `_owner`.
      *
      * @dev  Intended for use by token implementation functions
      * that update spending allowances. The only authorized caller
      * is the active implementation.
      *
      * @param  _owner  The account that will allow an on-behalf-of spend.
      * @param  _spender  The account that will spend on behalf of the owner.
      * @param  _value  The limit of what can be spent.
      */
    function setAllowance(
        address _owner,
        address _spender,
        uint256 _value
    )
        public
        onlyImpl
    {
        allowed[_owner][_spender] = _value;
    }

    /** @notice  Sets the balance of `_owner` to `_newBalance`.
      *
      * @dev  Intended for use by token implementation functions
      * that update balances. The only authorized caller
      * is the active implementation.
      *
      * @param  _owner  The account that will hold a new balance.
      * @param  _newBalance  The balance to set.
      */
    function setBalance(
        address _owner,
        uint256 _newBalance
    )
        public
        onlyImpl
    {
        balances[_owner] = _newBalance;
    }

    /** @notice Adds `_balanceIncrease` to `_owner`'s balance.
      *
      * @dev  Intended for use by token implementation functions
      * that update balances. The only authorized caller
      * is the active implementation.
      * WARNING: the caller is responsible for preventing overflow.
      *
      * @param  _owner  The account that will hold a new balance.
      * @param  _balanceIncrease  The balance to add.
      */
    function addBalance(
        address _owner,
        uint256 _balanceIncrease
    )
        public
        onlyImpl
    {
        balances[_owner] = balances[_owner] + _balanceIncrease;
    }
}

Read Contract

allowance 0xdd62ed3e → uint256
balanceOf 0x70a08231 → uint256
custodian 0x375b74c3 → address
custodianChangeReqs 0xcf6e4488 → address
erc20Proxy 0x7f555b03 → address
erc20Store 0xf602c312 → address
lockRequestCount 0xcb81fecf → uint256
pendingPrintMap 0x04ff7d3f → address, uint256
sweepMsg 0xde5007ff → bytes32
sweeper 0x9189a59e → address
sweptSet 0xea5fbfd5 → bool
totalSupply 0x18160ddd → uint256

Write Contract 13 functions

These functions modify contract state and require a wallet transaction to execute.

approveWithSender 0x89064fd2
address _sender
address _spender
uint256 _value
returns: bool
batchTransfer 0x88d695b2
address[] _tos
uint256[] _values
returns: bool
burn 0x42966c68
uint256 _value
returns: bool
confirmCustodianChange 0x3a8343ee
bytes32 _lockId
confirmPrint 0x380ba30c
bytes32 _lockId
decreaseApprovalWithSender 0x61e1077d
address _sender
address _spender
uint256 _subtractedValue
returns: bool
enableSweep 0xb7279ca6
uint8[] _vs
bytes32[] _rs
bytes32[] _ss
address _to
increaseApprovalWithSender 0x2e0179b5
address _sender
address _spender
uint256 _addedValue
returns: bool
replaySweep 0xeb55b2a3
address[] _froms
address _to
requestCustodianChange 0x15b21082
address _proposedCustodian
returns: bytes32
requestPrint 0xbe23d291
address _receiver
uint256 _value
returns: bytes32
transferFromWithSender 0x5d5e22cd
address _sender
address _from
address _to
uint256 _value
returns: bool
transferWithSender 0xdfe0f0ca
address _sender
address _to
uint256 _value
returns: bool

Recent Transactions

This address has 1 on-chain transactions, but only 1.3% of the chain is indexed. Transactions will appear as indexing progresses. View on Etherscan →