Forkchoice Ethereum Mainnet

Address Contract Partially Verified

Address 0x723B51b72Ae89A3d0c2a2760f0458307a1Baa191
Balance 0 ETH
Nonce 1
Code Size 4221 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

4221 bytes
0x608060405234801561001057600080fd5b50600436106100935760003560e01c80636e519d10116100665780636e519d10146101dd57806370a082311461027d578063a457c2d7146102b5578063dd62ed3e146102e1578063de4adfc31461030f57610093565b8063095ea7b31461009857806323b872dd146100d85780632d657fa51461010e57806339509351146101b1575b600080fd5b6100c4600480360360408110156100ae57600080fd5b506001600160a01b038135169060200135610359565b604080519115158252519081900360200190f35b6100c4600480360360608110156100ee57600080fd5b506001600160a01b0381358116916020810135909116906040013561036f565b6100c4600480360360e081101561012457600080fd5b6001600160a01b038235811692602081013590911691604082013591606081013515159160808201359160a08101359181019060e0810160c082013564010000000081111561017257600080fd5b82018360208201111561018457600080fd5b803590602001918460018302840111640100000000831117156101a657600080fd5b50909250905061056b565b6100c4600480360360408110156101c757600080fd5b506001600160a01b038135169060200135610757565b610264600480360360808110156101f357600080fd5b6001600160e01b0319823516919081019060408101602082013564010000000081111561021f57600080fd5b82018360208201111561023157600080fd5b8035906020019184600183028401116401000000008311171561025357600080fd5b919350915080359060200135610796565b6040805192835290151560208301528051918290030190f35b6102a36004803603602081101561029357600080fd5b50356001600160a01b0316610848565b60408051918252519081900360200190f35b6100c4600480360360408110156102cb57600080fd5b506001600160a01b038135169060200135610855565b6102a3600480360360408110156102f757600080fd5b506001600160a01b038135811691602001351661088f565b6100c4600480360360c081101561032557600080fd5b506001600160a01b038135811691602081013590911690604081013590606081013515159060808101359060a001356108b8565b6000610366338484610ac8565b50600192915050565b6001600160a01b038316600090815260208181526040808320338452909152812054806103e3576040805162461bcd60e51b815260206004820152601c60248201527f4e6f20616c6c6f77616e63652073657420666f722063616c6c65722e00000000604482015290519081900360640190fd5b600019811461044e5782811015610441576040805162461bcd60e51b815260206004820152601760248201527f496e73756666696369656e7420616c6c6f77616e63652e000000000000000000604482015290519081900360640190fd5b61044e8533858403610ac8565b846001600160a01b031663cc90530a85856040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b1580156104ae57600080fd5b505af11580156104c2573d6000803e3d6000fd5b505050506040513d60208110156104d857600080fd5b50519150816105185760405162461bcd60e51b815260040180806020018281038252602c815260200180610fe2602c913960400191505060405180910390fd5b836001600160a01b0316856001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a3509392505050565b600084158061057a5750844211155b6105c7576040805162461bcd60e51b815260206004820152601960248201527826b2ba3096ba3930b739b0b1ba34b7b71032bc3834b932b21760391b604482015290519081900360640190fd5b604080516001600160a01b03808c16602080840191909152908b168284015260608281018b90528915156080808501919091528451808503909101815260a084019094523080821b60c08501908152632d657fa560e01b60d4860181905260d886018c905260f886018b905286519396929590948c948c94939261011801918401908083835b6020831061066c5780518252601f19909201916020918201910161064d565b6001836020036101000a0380198251168184511680821785525050505050509050019550505050505060405160208183030381529060405290506106e78a8286868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610bb292505050565b6001600160a01b03808b16600090815260208181526040808320938d16835292905290812054908861072857610723828b63ffffffff610e9c16565b610738565b610738828b63ffffffff610ef916565b90506107458c8c83610ac8565b5060019b9a5050505050505050505050565b336000818152602081815260408083206001600160a01b03871684529091528120549091610366918590610791908663ffffffff610ef916565b610ac8565b60008030878585898960405160200180876001600160a01b03166001600160a01b031660601b8152601401866001600160e01b0319166001600160e01b03191681526004018581526020018481526020018383808284376040805191909301818103601f19018252835280516020918201206000818152600190925292902054919a505060ff16159650508515945061083c9350505050575083158061083c5750834211155b90509550959350505050565b6001600160a01b03163190565b336000818152602081815260408083206001600160a01b03871684529091528120549091610366918590610791908663ffffffff610e9c16565b6001600160a01b0391821660009081526020818152604080832093909416825291909152205490565b60008215806108c75750824211155b610914576040805162461bcd60e51b815260206004820152601960248201527826b2ba3096ba3930b739b0b1ba34b7b71032bc3834b932b21760391b604482015290519081900360640190fd5b336001600160a01b03881614806109335750336001600160a01b038716145b61096e5760405162461bcd60e51b815260040180806020018281038252603a81526020018061100e603a913960400191505060405180910390fd5b604080516001600160a01b03808a166020808401919091529089168284015260608281018990528715156080808501919091528451808503909101815260a084019094523080821b60c08501908152632d657fa560e01b60d4860181905260d886018a905260f8860189905286519396929590948a948a94939261011801918401908083835b60208310610a135780518252601f1990920191602091820191016109f4565b51815160209384036101000a60001901801990921691161790526040805192909401828103601f19018352845281518282012060008181526001909252939020549099509197505060ff16159450610aa193505050505760405162461bcd60e51b8152600401808060200182810382526021815260200180610f7d6021913960400191505060405180910390fd5b6000908152600160208190526040909120805460ff19168217905598975050505050505050565b6001600160a01b038316610b0d5760405162461bcd60e51b8152600401808060200182810382526023815260200180610fbf6023913960400191505060405180910390fd5b6001600160a01b038216610b525760405162461bcd60e51b8152600401808060200182810382526022815260200180610f5b6022913960400191505060405180910390fd5b6001600160a01b0380841660008181526020818152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b81516020808401919091206000818152600190925260409091205460ff1615610c0c5760405162461bcd60e51b8152600401808060200182810382526021815260200180610f9e6021913960400191505060405180910390fd5b6000818152600160208181526040808420805460ff191690931790925581517f19457468657265756d205369676e6564204d6573736167653a0a33320000000081830152603c80820186905283518083039091018152605c82018452805190830120607c8201818152609c8301948552885160bc8401528851919560609587958b959394919360dc019290860191908190849084905b83811015610cba578181015183820152602001610ca2565b50505050905090810190601f168015610ce75780820380516001836020036101000a031916815260200191505b5060408051601f198184030181528282526320c13b0b60e01b835260048301918252805160448401528051909750600096506001600160a01b038d1695506320c13b0b94508793508a92829160248201916064019060208701908083838d5b83811015610d5e578181015183820152602001610d46565b50505050905090810190601f168015610d8b5780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b83811015610dbe578181015183820152602001610da6565b50505050905090810190601f168015610deb5780820380516001836020036101000a031916815260200191505b5094505050505060206040518083038186803b158015610e0a57600080fd5b505afa158015610e1e573d6000803e3d6000fd5b505050506040513d6020811015610e3457600080fd5b505190506001600160e01b031981166320c13b0b60e01b14610e93576040805162461bcd60e51b815260206004820152601360248201527224b73b30b634b21039b4b3b730ba3ab932b99760691b604482015290519081900360640190fd5b50505050505050565b600082821115610ef3576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b600082820183811015610f53576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b939250505056fe45524332303a20617070726f766520746f20746865207a65726f20616464726573734d6574612d7472616e73616374696f6e20616c726561647920696e76616c69642e4d6574612d7472616e73616374696f6e206e6f206c6f6e6765722076616c69642e45524332303a20617070726f766520666f7220746865207a65726f20616464726573734f776e657220646964206e6f7420636f6e6669726d2061207375636365737366756c207472616e736665722e4f6e6c79206f776e6572206f72207370656e646572206d61792063616e63656c206120676976656e206d6574612d7472616e73616374696f6e2ea2646970667358221220b17ebc8317def0291fa768f98bd29f0c25a1f9b1d6b7e00052a77479d8b8e15d64736f6c63430006080033

Verified Source Code Partial Match

Compiler: v0.6.8+commit.0bbfe453 EVM: istanbul Optimization: Yes (200 runs)
EtherizerV2.sol 393 lines
pragma solidity 0.6.8; // optimization runs: 200, evm version: istanbul


interface ERC1271Interface {
    function isValidSignature(
        bytes calldata data, bytes calldata signatures
    ) external view returns (bytes4 magicValue);
}


interface EtherizedInterface {
    function triggerEtherTransfer(
        address target, uint256 value
    ) external returns (bool success);
}


interface EtherizerV2Interface {
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);

    function transferFrom(
        EtherizedInterface from, address payable to, uint256 value
    ) external returns (bool success);
    function approve(address spender, uint256 value) external returns (bool success);
    function increaseAllowance(
      address spender, uint256 addedValue
    ) external returns (bool success);
    function decreaseAllowance(
      address spender, uint256 subtractedValue
    ) external returns (bool success);
    function modifyAllowanceViaMetaTransaction(
        address owner,
        address spender,
        uint256 value,
        bool increase,
        uint256 expiration,
        bytes32 salt,
        bytes calldata signatures
    ) external returns (bool success);
    function cancelAllowanceModificationMetaTransaction(
        address owner,
        address spender,
        uint256 value,
        bool increase,
        uint256 expiration,
        bytes32 salt
    ) external returns (bool success);

    function getMetaTransactionMessageHash(
        bytes4 functionSelector, bytes calldata arguments, uint256 expiration, bytes32 salt
    ) external view returns (bytes32 digest, bool valid);
    function balanceOf(address account) external view returns (uint256 amount);
    function allowance(address owner, address spender) external view returns (uint256 amount);
}


library SafeMath {
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction overflow");
        uint256 c = a - b;

        return c;
    }
}


/**
 * @title EtherizerV2
 * @author 0age
 * @notice Etherizer is a contract for enabling "approvals" for performing
 * Ether transfers from compliant accounts via either standard ERC20 methods
 * or meta-transactions. A "compliant" account must be a smart contract that
 * implements a `triggerEtherTransfer` function that is only callable by this
 * contract as well as the `isValidSignature` function specified by ERC-1271
 * for enabling meta-transaction functionality. Be warned that any approved
 * spender can initiate calls from the owner's account — though data will be
 * empty, considerable caution is still merited when granting any approvals.
 */
contract EtherizerV2 is EtherizerV2Interface {
    using SafeMath for uint256;
    
    // Maintain a mapping of Ether allowances.
    mapping (address => mapping (address => uint256)) private _allowances;

    // Maintain a mapping of invalid meta-transaction message hashes.
    mapping (bytes32 => bool) private _invalidMetaTxHashes;

  /**
   * @notice Trigger a call from `owner` to `recipient` with `amount`
   * Ether as long as `msg.sender` has sufficient allowance, `owner` is a
   * compliant contract that implements `triggerEtherTransfer`, and
   * `recipient` is able to receive Ether transfers.
   * @param owner address The account to perform the call from.
   * @param recipient address The account to call.
   * @param amount uint256 The amount of Ether to transfer.
   * @return success A boolean indicating whether the call was successful.
   */
  function transferFrom(
    EtherizedInterface owner,
    address payable recipient,
    uint256 amount
  ) external override returns (bool success) {
    // Get the current allowance granted by the owner to the caller.
    uint256 callerAllowance = _allowances[address(owner)][msg.sender];
    
    // Block attempts to trigger calls when no allowance has been set.
    require(callerAllowance != 0, "No allowance set for caller.");
    
    // Reduce the allowance if it is not set to full allowance.
    if (callerAllowance != uint256(-1)) {
      require(callerAllowance >= amount, "Insufficient allowance.");
      _approve(
          address(owner), msg.sender, callerAllowance - amount
      ); // overflow safe (condition already checked).
    }
    
    // Trigger the call from the owner and revert if success is not returned.
    success = owner.triggerEtherTransfer(recipient, amount);
    require(success, "Owner did not confirm a successful transfer.");

    // Emit an event with information regarding the triggered call.
    emit Transfer(address(owner), recipient, amount);
  }

  /**
   * @notice Approve `spender` to transfer up to `value` Ether on behalf of
   * `msg.sender`.
   * @param spender address The account to grant the allowance.
   * @param value uint256 The size of the allowance to grant.
   * @return success A boolean indicating whether the approval was successful.
   */
  function approve(
    address spender, uint256 value
  ) external override returns (bool success) {
    _approve(msg.sender, spender, value);
    success = true;
  }

  /**
   * @notice Increase the current allowance of `spender` by `value` Ether.
   * @param spender address The account to grant the additional allowance.
   * @param addedValue uint256 The amount to increase the allowance by.
   * @return success A boolean indicating whether the modification was
   * successful.
   */
  function increaseAllowance(
    address spender, uint256 addedValue
  ) external override returns (bool success) {
    _approve(
      msg.sender, spender, _allowances[msg.sender][spender].add(addedValue)
    );
    success = true;
  }

  /**
   * @notice Decrease the current allowance of `spender` by `value` Ether.
   * @param spender address The account to decrease the allowance for.
   * @param subtractedValue uint256 The amount to subtract from the allowance.
   * @return success A boolean indicating whether the modification was
   * successful.
   */
  function decreaseAllowance(
    address spender, uint256 subtractedValue
  ) external override returns (bool success) {
    _approve(
      msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue)
    );
    success = true;
  }
  
  /**
   * @notice Modify the current allowance of `spender` for `owner` by `value`
   * Ether, increasing it if `increase` is true, otherwise decreasing it, via a
   * meta-transaction that expires at `expiration` (or does not expire if the
   * value is zero) and uses `salt` as an additional input, validated using
   * `signatures`.
   * @param owner address The account granting the modified allowance.
   * @param spender address The account to modify the allowance for.
   * @param value uint256 The amount to modify the allowance by.
   * @param increase bool A flag that indicates whether the allowance will be
   * increased by the specified value (if true) or decreased by it (if false).
   * @param expiration uint256 A timestamp indicating how long the modification
   * meta-transaction is valid for - a value of zero will signify no expiration.
   * @param salt bytes32 An arbitrary salt to be provided as an additional input
   * to the hash digest used to validate the signatures.
   * @param signatures bytes A signature, or collection of signatures, that the
   * owner must provide in order to authorize the meta-transaction. If the
   * account of the owner does not have any runtime code deployed to it, the
   * signature will be verified using ecrecover; otherwise, it will be supplied
   * to the owner along with the message digest and context via ERC-1271 for
   * validation.
   * @return success A boolean indicating whether the modification was
   * successful.
   */
  function modifyAllowanceViaMetaTransaction(
    address owner,
    address spender,
    uint256 value,
    bool increase,
    uint256 expiration,
    bytes32 salt,
    bytes calldata signatures
  ) external override returns (bool success) {
    require(expiration == 0 || now <= expiration, "Meta-transaction expired.");

    // Construct the meta-transaction's "context" information  and validate it.
    bytes memory context = abi.encodePacked(
      address(this),
      this.modifyAllowanceViaMetaTransaction.selector,
      expiration,
      salt,
      abi.encode(owner, spender, value, increase)
    );
    _validateMetaTransaction(owner, context, signatures);

    // Calculate new allowance by applying modification to current allowance.
    uint256 currentAllowance = _allowances[owner][spender];
    uint256 newAllowance = (
      increase ? currentAllowance.add(value) : currentAllowance.sub(value)
    );

    // Modify the allowance.
    _approve(owner, spender, newAllowance);
    success = true;
  }

  /**
   * @notice Cancel a specific meta-transaction for modifying an allowance. The
   * designated owner or spender can both cancel the given meta-transaction.
   * @param owner address The account granting the modified allowance.
   * @param spender address The account to modify the allowance for.
   * @param value uint256 The amount to modify the allowance by.
   * @param increase bool A flag that indicates whether the allowance will be
   * increased by the specified value (if true) or decreased by it (if false).
   * @param expiration uint256 A timestamp indicating how long the modification
   * meta-transaction is valid for - a value of zero will signify no expiration.
   * @param salt bytes32 An arbitrary salt to be provided as an additional input
   * to the hash digest used to validate the signatures.
   * @return success A boolean indicating whether the cancellation was
   * successful.
   */
  function cancelAllowanceModificationMetaTransaction(
    address owner,
    address spender,
    uint256 value,
    bool increase,
    uint256 expiration,
    bytes32 salt
  ) external override returns (bool success) {
    require(expiration == 0 || now <= expiration, "Meta-transaction expired.");
    require(
        msg.sender == owner || msg.sender == spender,
        "Only owner or spender may cancel a given meta-transaction."
    );

    // Construct the meta-transaction's "context" information.
    bytes memory context = abi.encodePacked(
      address(this),
      this.modifyAllowanceViaMetaTransaction.selector,
      expiration,
      salt,
      abi.encode(owner, spender, value, increase)
    );

    // Construct the message hash using the provided context.
    bytes32 messageHash = keccak256(context);

    // Ensure message hash has not been used or cancelled and invalidate it.
    require(
        !_invalidMetaTxHashes[messageHash], "Meta-transaction already invalid."
    );
    _invalidMetaTxHashes[messageHash] = true;

    success = true;
  }
 
  /**
   * @notice View function to determine a meta-transaction message hash, and to
   * determine if it is still valid (i.e. it has not yet been used and is not
   * expired). The returned message hash will need to be prefixed using EIP-191
   * 0x45 and hashed again in order to generate a final digest for the required
   * signature - in other words, the same procedure utilized by `eth_Sign`.
   * @param functionSelector bytes4 The function selector for the given
   * meta-transaction. There is only one function selector available for V1:
   * `0x2d657fa5` (the selector for `modifyAllowanceViaMetaTransaction`).
   * @param arguments bytes The abi-encoded function arguments (aside from the
   * `expiration`, `salt`, and `signatures` arguments) that should be supplied
   * to the given function.
   * @param expiration uint256 A timestamp indicating how long the given
   * meta-transaction is valid for - a value of zero will signify no expiration.
   * @param salt bytes32 An arbitrary salt to be provided as an additional input
   * to the hash digest used to validate the signatures.
   * @return messageHash The message hash corresponding to the meta-transaction.
   */
  function getMetaTransactionMessageHash(
    bytes4 functionSelector,
    bytes calldata arguments,
    uint256 expiration,
    bytes32 salt
  ) external view override returns (bytes32 messageHash, bool valid) {
    // Construct the meta-transaction's message hash based on relevant context.
    messageHash = keccak256(
      abi.encodePacked(
        address(this), functionSelector, expiration, salt, arguments
      )
    );

    // The meta-transaction is valid if it has not been used and is not expired.
    valid = (
      !_invalidMetaTxHashes[messageHash] && (expiration == 0 || now <= expiration)
    );
  }
  
  /**
   * @notice View function to get the total Ether balance of an account.
   * @param account address The account to check the Ether balance for.
   * @return amount The Ether balance of the given account.
   */
  function balanceOf(
      address account
  ) external view override returns (uint256 amount) {
    amount = account.balance;
  }
  
  /**
   * @notice View function to get the total allowance that `spender` has to
   * transfer Ether from the `owner` account using `triggerCallFrom`.
   * @param owner address The account that is granting the allowance.
   * @param spender address The account that has been granted the allowance.
   * @return etherAllowance The allowance of the given spender for the given
   * owner.
   */
  function allowance(
    address owner, address spender
  ) external view override returns (uint256 etherAllowance) {
    etherAllowance = _allowances[owner][spender];
  }
  
  /**
   * @notice Private function to set the allowance for `spender` to transfer up
   * to `value` tokens on behalf of `owner`.
   * @param owner address The account that has granted the allowance.
   * @param spender address The account to grant the allowance.
   * @param value uint256 The size of the allowance to grant.
   */
  function _approve(address owner, address spender, uint256 value) private {
    require(owner != address(0), "ERC20: approve for the zero address");
    require(spender != address(0), "ERC20: approve to the zero address");

    _allowances[owner][spender] = value;
    emit Approval(owner, spender, value);
  }

  /**
   * @notice Private function to enforce that a given Meta-transaction
   * has not been used before and that the signature is valid according
   * to the owner (using ERC-1271).
   * @param owner address The account originating the meta-transaction.
   * @param context bytes Information about the meta-transaction.
   * @param signatures bytes Signature or signatures used to validate
   * the meta-transaction.
   */  
  function _validateMetaTransaction(
    address owner, bytes memory context, bytes memory signatures
  ) private {
    // Construct the message hash using the provided context.
    bytes32 messageHash = keccak256(context);

    // Ensure message hash has not been used or cancelled and invalidate it.
    require(
        !_invalidMetaTxHashes[messageHash], "Meta-transaction no longer valid."
    );
    _invalidMetaTxHashes[messageHash] = true;

    // Construct the digest to compare signatures against using EIP-191 0x45.
    bytes32 digest = keccak256(
      abi.encodePacked("\x19Ethereum Signed Message:\n32", messageHash)
    );

    // Validate via ERC-1271 against the owner account.
    bytes memory data = abi.encode(digest, context);
    bytes4 magic = ERC1271Interface(owner).isValidSignature(data, signatures);
    require(magic == bytes4(0x20c13b0b), "Invalid signatures.");  
  }
}

Read Contract

allowance 0xdd62ed3e → uint256
balanceOf 0x70a08231 → uint256
getMetaTransactionMessageHash 0x6e519d10 → bytes32, bool

Write Contract 6 functions

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

approve 0x095ea7b3
address spender
uint256 value
returns: bool
cancelAllowanceModificationMetaTransaction 0xde4adfc3
address owner
address spender
uint256 value
bool increase
uint256 expiration
bytes32 salt
returns: bool
decreaseAllowance 0xa457c2d7
address spender
uint256 subtractedValue
returns: bool
increaseAllowance 0x39509351
address spender
uint256 addedValue
returns: bool
modifyAllowanceViaMetaTransaction 0x2d657fa5
address owner
address spender
uint256 value
bool increase
uint256 expiration
bytes32 salt
bytes signatures
returns: bool
transferFrom 0x23b872dd
address owner
address recipient
uint256 amount
returns: bool

Recent Transactions

No transactions found for this address