ETH Price: $2,437.12 (+0.58%)

Transaction Decoder

Block:
14205680 at Feb-14-2022 05:44:05 PM +UTC
Transaction Fee:
0.0160245268248368 ETH $39.05
Gas Used:
214,268 Gas / 74.7873076 Gwei

Emitted Events:

87 0x495f947276749ce646f68ac8c248420045cb7b5e.0xc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62( 0xc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62, 0x000000000000000000000000c3e166f94ee5e14864c011617131a95bf6a9b11f, 0x00000000000000000000000089645ea8c9b5b868b2a7db32f43a0c29f34ececb, 0x000000000000000000000000dc58c995b05745de5f1f0da7407fd59b87178f18, 2aebfbe7beb886f46eb4876baa9770e2c659a6c7000000000000640000000001, 0000000000000000000000000000000000000000000000000000000000000001 )
88 0x495f947276749ce646f68ac8c248420045cb7b5e.0xc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62( 0xc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62, 0x000000000000000000000000c3e166f94ee5e14864c011617131a95bf6a9b11f, 0x00000000000000000000000089645ea8c9b5b868b2a7db32f43a0c29f34ececb, 0x000000000000000000000000dc58c995b05745de5f1f0da7407fd59b87178f18, 2aebfbe7beb886f46eb4876baa9770e2c659a6c7000000000000660000000001, 0000000000000000000000000000000000000000000000000000000000000001 )

Account State Difference:

  Address   Before After State Difference Code
(Poolin 2)
1,157.687394455509988308 Eth1,157.687715857509988308 Eth0.000321402
0x495f9472...045cb7b5e
0x89645ea8...9F34eCEcb
0.115664711713515468 Eth
Nonce: 50
0.099640184888678668 Eth
Nonce: 51
0.0160245268248368

Execution Trace

OwnableDelegateProxy.3f801f91( )
  • AuthenticatedProxy.proxyAssert( dest=0xC99f70bFD82fb7c8f8191fdfbFB735606b15e5c5, howToCall=1, calldata=0x68F0BCAA000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000E0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001A00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000495F947276749CE646F68AC8C248420045CB7B5E000000000000000000000000495F947276749CE646F68AC8C248420045CB7B5E000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000C400000000000000000000000000000000000000000000000000000000000000C40000000000000000000000000000000000000000000000000000000000000188F242432A00000000000000000000000089645EA8C9B5B868B2A7DB32F43A0C29F34ECECB000000000000000000000000DC58C995B05745DE5F1F0DA7407FD59B87178F182AEBFBE7BEB886F46EB4876BAA9770E2C659A6C7000000000000640000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000000000000000000000000000000000000000000F242432A00000000000000000000000089645EA8C9B5B868B2A7DB32F43A0C29F34ECECB000000000000000000000000DC58C995B05745DE5F1F0DA7407FD59B87178F182AEBFBE7BEB886F46EB4876BAA9770E2C659A6C7000000000000660000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 )
    • WyvernAtomicizer.atomicize( addrs=[0x495f947276749Ce646f68AC8c248420045cb7b5e, 0x495f947276749Ce646f68AC8c248420045cb7b5e], values=[0, 0], calldataLengths=[196, 196], calldatas=0xF242432A00000000000000000000000089645EA8C9B5B868B2A7DB32F43A0C29F34ECECB000000000000000000000000DC58C995B05745DE5F1F0DA7407FD59B87178F182AEBFBE7BEB886F46EB4876BAA9770E2C659A6C7000000000000640000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000000000000000000000000000000000000000000F242432A00000000000000000000000089645EA8C9B5B868B2A7DB32F43A0C29F34ECECB000000000000000000000000DC58C995B05745DE5F1F0DA7407FD59B87178F182AEBFBE7BEB886F46EB4876BAA9770E2C659A6C7000000000000660000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000A00000000000000000000000000000000000000000000000000000000000000000 )
      • OpenSea: OPENSTORE Token.f242432a( )
        • WyvernProxyRegistry.proxies( 0x89645ea8c9B5B868B2a7db32f43a0C29F34eCEcb ) => ( 0xc3e166F94eE5E14864C011617131a95Bf6a9B11f )
        • OpenSea: OPENSTORE Token.f242432a( )
          • WyvernProxyRegistry.proxies( 0x89645ea8c9B5B868B2a7db32f43a0C29F34eCEcb ) => ( 0xc3e166F94eE5E14864C011617131a95Bf6a9B11f )
            File 1 of 4: OwnableDelegateProxy
            contract OwnedUpgradeabilityStorage {
            
              // Current implementation
              address internal _implementation;
            
              // Owner of the contract
              address private _upgradeabilityOwner;
            
              /**
               * @dev Tells the address of the owner
               * @return the address of the owner
               */
              function upgradeabilityOwner() public view returns (address) {
                return _upgradeabilityOwner;
              }
            
              /**
               * @dev Sets the address of the owner
               */
              function setUpgradeabilityOwner(address newUpgradeabilityOwner) internal {
                _upgradeabilityOwner = newUpgradeabilityOwner;
              }
            
              /**
              * @dev Tells the address of the current implementation
              * @return address of the current implementation
              */
              function implementation() public view returns (address) {
                return _implementation;
              }
            
              /**
              * @dev Tells the proxy type (EIP 897)
              * @return Proxy type, 2 for forwarding proxy
              */
              function proxyType() public pure returns (uint256 proxyTypeId) {
                return 2;
              }
            }
            
            
            
            contract Proxy {
            
              /**
              * @dev Tells the address of the implementation where every call will be delegated.
              * @return address of the implementation to which it will be delegated
              */
              function implementation() public view returns (address);
            
              /**
              * @dev Tells the type of proxy (EIP 897)
              * @return Type of proxy, 2 for upgradeable proxy
              */
              function proxyType() public pure returns (uint256 proxyTypeId);
            
              /**
              * @dev Fallback function allowing to perform a delegatecall to the given implementation.
              * This function will return whatever the implementation call returns
              */
              function () payable public {
                address _impl = implementation();
                require(_impl != address(0));
            
                assembly {
                  let ptr := mload(0x40)
                  calldatacopy(ptr, 0, calldatasize)
                  let result := delegatecall(gas, _impl, ptr, calldatasize, 0, 0)
                  let size := returndatasize
                  returndatacopy(ptr, 0, size)
            
                  switch result
                  case 0 { revert(ptr, size) }
                  default { return(ptr, size) }
                }
              }
            }
            
            contract OwnedUpgradeabilityProxy is Proxy, OwnedUpgradeabilityStorage {
              /**
              * @dev Event to show ownership has been transferred
              * @param previousOwner representing the address of the previous owner
              * @param newOwner representing the address of the new owner
              */
              event ProxyOwnershipTransferred(address previousOwner, address newOwner);
            
              /**
              * @dev This event will be emitted every time the implementation gets upgraded
              * @param implementation representing the address of the upgraded implementation
              */
              event Upgraded(address indexed implementation);
            
              /**
              * @dev Upgrades the implementation address
              * @param implementation representing the address of the new implementation to be set
              */
              function _upgradeTo(address implementation) internal {
                require(_implementation != implementation);
                _implementation = implementation;
                emit Upgraded(implementation);
              }
            
              /**
              * @dev Throws if called by any account other than the owner.
              */
              modifier onlyProxyOwner() {
                require(msg.sender == proxyOwner());
                _;
              }
            
              /**
               * @dev Tells the address of the proxy owner
               * @return the address of the proxy owner
               */
              function proxyOwner() public view returns (address) {
                return upgradeabilityOwner();
              }
            
              /**
               * @dev Allows the current owner to transfer control of the contract to a newOwner.
               * @param newOwner The address to transfer ownership to.
               */
              function transferProxyOwnership(address newOwner) public onlyProxyOwner {
                require(newOwner != address(0));
                emit ProxyOwnershipTransferred(proxyOwner(), newOwner);
                setUpgradeabilityOwner(newOwner);
              }
            
              /**
               * @dev Allows the upgradeability owner to upgrade the current implementation of the proxy.
               * @param implementation representing the address of the new implementation to be set.
               */
              function upgradeTo(address implementation) public onlyProxyOwner {
                _upgradeTo(implementation);
              }
            
              /**
               * @dev Allows the upgradeability owner to upgrade the current implementation of the proxy
               * and delegatecall the new implementation for initialization.
               * @param implementation representing the address of the new implementation to be set.
               * @param data represents the msg.data to bet sent in the low level call. This parameter may include the function
               * signature of the implementation to be called with the needed payload
               */
              function upgradeToAndCall(address implementation, bytes data) payable public onlyProxyOwner {
                upgradeTo(implementation);
                require(address(this).delegatecall(data));
              }
            }
            
            
            contract OwnableDelegateProxy is OwnedUpgradeabilityProxy {
            
                constructor(address owner, address initialImplementation, bytes calldata)
                    public
                {
                    setUpgradeabilityOwner(owner);
                    _upgradeTo(initialImplementation);
                    require(initialImplementation.delegatecall(calldata));
                }
            
            }

            File 2 of 4: AuthenticatedProxy
            pragma solidity ^0.4.13;
            
            contract Ownable {
              address public owner;
            
            
              event OwnershipRenounced(address indexed previousOwner);
              event OwnershipTransferred(
                address indexed previousOwner,
                address indexed newOwner
              );
            
            
              /**
               * @dev The Ownable constructor sets the original `owner` of the contract to the sender
               * account.
               */
              constructor() public {
                owner = msg.sender;
              }
            
              /**
               * @dev Throws if called by any account other than the owner.
               */
              modifier onlyOwner() {
                require(msg.sender == owner);
                _;
              }
            
              /**
               * @dev Allows the current owner to transfer control of the contract to a newOwner.
               * @param newOwner The address to transfer ownership to.
               */
              function transferOwnership(address newOwner) public onlyOwner {
                require(newOwner != address(0));
                emit OwnershipTransferred(owner, newOwner);
                owner = newOwner;
              }
            
              /**
               * @dev Allows the current owner to relinquish control of the contract.
               */
              function renounceOwnership() public onlyOwner {
                emit OwnershipRenounced(owner);
                owner = address(0);
              }
            }
            
            contract ERC20Basic {
              function totalSupply() public view returns (uint256);
              function balanceOf(address who) public view returns (uint256);
              function transfer(address to, uint256 value) public returns (bool);
              event Transfer(address indexed from, address indexed to, uint256 value);
            }
            
            contract ERC20 is ERC20Basic {
              function allowance(address owner, address spender)
                public view returns (uint256);
            
              function transferFrom(address from, address to, uint256 value)
                public returns (bool);
            
              function approve(address spender, uint256 value) public returns (bool);
              event Approval(
                address indexed owner,
                address indexed spender,
                uint256 value
              );
            }
            
            contract ProxyRegistry is Ownable {
            
                /* DelegateProxy implementation contract. Must be initialized. */
                address public delegateProxyImplementation;
            
                /* Authenticated proxies by user. */
                mapping(address => OwnableDelegateProxy) public proxies;
            
                /* Contracts pending access. */
                mapping(address => uint) public pending;
            
                /* Contracts allowed to call those proxies. */
                mapping(address => bool) public contracts;
            
                /* Delay period for adding an authenticated contract.
                   This mitigates a particular class of potential attack on the Wyvern DAO (which owns this registry) - if at any point the value of assets held by proxy contracts exceeded the value of half the WYV supply (votes in the DAO),
                   a malicious but rational attacker could buy half the Wyvern and grant themselves access to all the proxy contracts. A delay period renders this attack nonthreatening - given two weeks, if that happened, users would have
                   plenty of time to notice and transfer their assets.
                */
                uint public DELAY_PERIOD = 2 weeks;
            
                /**
                 * Start the process to enable access for specified contract. Subject to delay period.
                 *
                 * @dev ProxyRegistry owner only
                 * @param addr Address to which to grant permissions
                 */
                function startGrantAuthentication (address addr)
                    public
                    onlyOwner
                {
                    require(!contracts[addr] && pending[addr] == 0);
                    pending[addr] = now;
                }
            
                /**
                 * End the process to nable access for specified contract after delay period has passed.
                 *
                 * @dev ProxyRegistry owner only
                 * @param addr Address to which to grant permissions
                 */
                function endGrantAuthentication (address addr)
                    public
                    onlyOwner
                {
                    require(!contracts[addr] && pending[addr] != 0 && ((pending[addr] + DELAY_PERIOD) < now));
                    pending[addr] = 0;
                    contracts[addr] = true;
                }
            
                /**
                 * Revoke access for specified contract. Can be done instantly.
                 *
                 * @dev ProxyRegistry owner only
                 * @param addr Address of which to revoke permissions
                 */    
                function revokeAuthentication (address addr)
                    public
                    onlyOwner
                {
                    contracts[addr] = false;
                }
            
                /**
                 * Register a proxy contract with this registry
                 *
                 * @dev Must be called by the user which the proxy is for, creates a new AuthenticatedProxy
                 * @return New AuthenticatedProxy contract
                 */
                function registerProxy()
                    public
                    returns (OwnableDelegateProxy proxy)
                {
                    require(proxies[msg.sender] == address(0));
                    proxy = new OwnableDelegateProxy(msg.sender, delegateProxyImplementation, abi.encodeWithSignature("initialize(address,address)", msg.sender, address(this)));
                    proxies[msg.sender] = proxy;
                    return proxy;
                }
            
            }
            
            contract TokenRecipient {
                event ReceivedEther(address indexed sender, uint amount);
                event ReceivedTokens(address indexed from, uint256 value, address indexed token, bytes extraData);
            
                /**
                 * @dev Receive tokens and generate a log event
                 * @param from Address from which to transfer tokens
                 * @param value Amount of tokens to transfer
                 * @param token Address of token
                 * @param extraData Additional data to log
                 */
                function receiveApproval(address from, uint256 value, address token, bytes extraData) public {
                    ERC20 t = ERC20(token);
                    require(t.transferFrom(from, this, value));
                    emit ReceivedTokens(from, value, token, extraData);
                }
            
                /**
                 * @dev Receive Ether and generate a log event
                 */
                function () payable public {
                    emit ReceivedEther(msg.sender, msg.value);
                }
            }
            
            contract OwnedUpgradeabilityStorage {
            
              // Current implementation
              address internal _implementation;
            
              // Owner of the contract
              address private _upgradeabilityOwner;
            
              /**
               * @dev Tells the address of the owner
               * @return the address of the owner
               */
              function upgradeabilityOwner() public view returns (address) {
                return _upgradeabilityOwner;
              }
            
              /**
               * @dev Sets the address of the owner
               */
              function setUpgradeabilityOwner(address newUpgradeabilityOwner) internal {
                _upgradeabilityOwner = newUpgradeabilityOwner;
              }
            
              /**
              * @dev Tells the address of the current implementation
              * @return address of the current implementation
              */
              function implementation() public view returns (address) {
                return _implementation;
              }
            
              /**
              * @dev Tells the proxy type (EIP 897)
              * @return Proxy type, 2 for forwarding proxy
              */
              function proxyType() public pure returns (uint256 proxyTypeId) {
                return 2;
              }
            }
            
            contract AuthenticatedProxy is TokenRecipient, OwnedUpgradeabilityStorage {
            
                /* Whether initialized. */
                bool initialized = false;
            
                /* Address which owns this proxy. */
                address public user;
            
                /* Associated registry with contract authentication information. */
                ProxyRegistry public registry;
            
                /* Whether access has been revoked. */
                bool public revoked;
            
                /* Delegate call could be used to atomically transfer multiple assets owned by the proxy contract with one order. */
                enum HowToCall { Call, DelegateCall }
            
                /* Event fired when the proxy access is revoked or unrevoked. */
                event Revoked(bool revoked);
            
                /**
                 * Initialize an AuthenticatedProxy
                 *
                 * @param addrUser Address of user on whose behalf this proxy will act
                 * @param addrRegistry Address of ProxyRegistry contract which will manage this proxy
                 */
                function initialize (address addrUser, ProxyRegistry addrRegistry)
                    public
                {
                    require(!initialized);
                    initialized = true;
                    user = addrUser;
                    registry = addrRegistry;
                }
            
                /**
                 * Set the revoked flag (allows a user to revoke ProxyRegistry access)
                 *
                 * @dev Can be called by the user only
                 * @param revoke Whether or not to revoke access
                 */
                function setRevoke(bool revoke)
                    public
                {
                    require(msg.sender == user);
                    revoked = revoke;
                    emit Revoked(revoke);
                }
            
                /**
                 * Execute a message call from the proxy contract
                 *
                 * @dev Can be called by the user, or by a contract authorized by the registry as long as the user has not revoked access
                 * @param dest Address to which the call will be sent
                 * @param howToCall Which kind of call to make
                 * @param calldata Calldata to send
                 * @return Result of the call (success or failure)
                 */
                function proxy(address dest, HowToCall howToCall, bytes calldata)
                    public
                    returns (bool result)
                {
                    require(msg.sender == user || (!revoked && registry.contracts(msg.sender)));
                    if (howToCall == HowToCall.Call) {
                        result = dest.call(calldata);
                    } else if (howToCall == HowToCall.DelegateCall) {
                        result = dest.delegatecall(calldata);
                    }
                    return result;
                }
            
                /**
                 * Execute a message call and assert success
                 * 
                 * @dev Same functionality as `proxy`, just asserts the return value
                 * @param dest Address to which the call will be sent
                 * @param howToCall What kind of call to make
                 * @param calldata Calldata to send
                 */
                function proxyAssert(address dest, HowToCall howToCall, bytes calldata)
                    public
                {
                    require(proxy(dest, howToCall, calldata));
                }
            
            }
            
            contract Proxy {
            
              /**
              * @dev Tells the address of the implementation where every call will be delegated.
              * @return address of the implementation to which it will be delegated
              */
              function implementation() public view returns (address);
            
              /**
              * @dev Tells the type of proxy (EIP 897)
              * @return Type of proxy, 2 for upgradeable proxy
              */
              function proxyType() public pure returns (uint256 proxyTypeId);
            
              /**
              * @dev Fallback function allowing to perform a delegatecall to the given implementation.
              * This function will return whatever the implementation call returns
              */
              function () payable public {
                address _impl = implementation();
                require(_impl != address(0));
            
                assembly {
                  let ptr := mload(0x40)
                  calldatacopy(ptr, 0, calldatasize)
                  let result := delegatecall(gas, _impl, ptr, calldatasize, 0, 0)
                  let size := returndatasize
                  returndatacopy(ptr, 0, size)
            
                  switch result
                  case 0 { revert(ptr, size) }
                  default { return(ptr, size) }
                }
              }
            }
            
            contract OwnedUpgradeabilityProxy is Proxy, OwnedUpgradeabilityStorage {
              /**
              * @dev Event to show ownership has been transferred
              * @param previousOwner representing the address of the previous owner
              * @param newOwner representing the address of the new owner
              */
              event ProxyOwnershipTransferred(address previousOwner, address newOwner);
            
              /**
              * @dev This event will be emitted every time the implementation gets upgraded
              * @param implementation representing the address of the upgraded implementation
              */
              event Upgraded(address indexed implementation);
            
              /**
              * @dev Upgrades the implementation address
              * @param implementation representing the address of the new implementation to be set
              */
              function _upgradeTo(address implementation) internal {
                require(_implementation != implementation);
                _implementation = implementation;
                emit Upgraded(implementation);
              }
            
              /**
              * @dev Throws if called by any account other than the owner.
              */
              modifier onlyProxyOwner() {
                require(msg.sender == proxyOwner());
                _;
              }
            
              /**
               * @dev Tells the address of the proxy owner
               * @return the address of the proxy owner
               */
              function proxyOwner() public view returns (address) {
                return upgradeabilityOwner();
              }
            
              /**
               * @dev Allows the current owner to transfer control of the contract to a newOwner.
               * @param newOwner The address to transfer ownership to.
               */
              function transferProxyOwnership(address newOwner) public onlyProxyOwner {
                require(newOwner != address(0));
                emit ProxyOwnershipTransferred(proxyOwner(), newOwner);
                setUpgradeabilityOwner(newOwner);
              }
            
              /**
               * @dev Allows the upgradeability owner to upgrade the current implementation of the proxy.
               * @param implementation representing the address of the new implementation to be set.
               */
              function upgradeTo(address implementation) public onlyProxyOwner {
                _upgradeTo(implementation);
              }
            
              /**
               * @dev Allows the upgradeability owner to upgrade the current implementation of the proxy
               * and delegatecall the new implementation for initialization.
               * @param implementation representing the address of the new implementation to be set.
               * @param data represents the msg.data to bet sent in the low level call. This parameter may include the function
               * signature of the implementation to be called with the needed payload
               */
              function upgradeToAndCall(address implementation, bytes data) payable public onlyProxyOwner {
                upgradeTo(implementation);
                require(address(this).delegatecall(data));
              }
            }
            
            contract OwnableDelegateProxy is OwnedUpgradeabilityProxy {
            
                constructor(address owner, address initialImplementation, bytes calldata)
                    public
                {
                    setUpgradeabilityOwner(owner);
                    _upgradeTo(initialImplementation);
                    require(initialImplementation.delegatecall(calldata));
                }
            
            }

            File 3 of 4: WyvernAtomicizer
            pragma solidity ^0.4.13;
            
            library WyvernAtomicizer {
            
                function atomicize (address[] addrs, uint[] values, uint[] calldataLengths, bytes calldatas)
                    public
                {
                    require(addrs.length == values.length && addrs.length == calldataLengths.length);
            
                    uint j = 0;
                    for (uint i = 0; i < addrs.length; i++) {
                        bytes memory calldata = new bytes(calldataLengths[i]);
                        for (uint k = 0; k < calldataLengths[i]; k++) {
                            calldata[k] = calldatas[j];
                            j++;
                        }
                        require(addrs[i].call.value(values[i])(calldata));
                    }
                }
            
            }

            File 4 of 4: WyvernProxyRegistry
            pragma solidity ^0.4.13;
            
            contract Ownable {
              address public owner;
            
            
              event OwnershipRenounced(address indexed previousOwner);
              event OwnershipTransferred(
                address indexed previousOwner,
                address indexed newOwner
              );
            
            
              /**
               * @dev The Ownable constructor sets the original `owner` of the contract to the sender
               * account.
               */
              constructor() public {
                owner = msg.sender;
              }
            
              /**
               * @dev Throws if called by any account other than the owner.
               */
              modifier onlyOwner() {
                require(msg.sender == owner);
                _;
              }
            
              /**
               * @dev Allows the current owner to transfer control of the contract to a newOwner.
               * @param newOwner The address to transfer ownership to.
               */
              function transferOwnership(address newOwner) public onlyOwner {
                require(newOwner != address(0));
                emit OwnershipTransferred(owner, newOwner);
                owner = newOwner;
              }
            
              /**
               * @dev Allows the current owner to relinquish control of the contract.
               */
              function renounceOwnership() public onlyOwner {
                emit OwnershipRenounced(owner);
                owner = address(0);
              }
            }
            
            contract ERC20Basic {
              function totalSupply() public view returns (uint256);
              function balanceOf(address who) public view returns (uint256);
              function transfer(address to, uint256 value) public returns (bool);
              event Transfer(address indexed from, address indexed to, uint256 value);
            }
            
            contract ERC20 is ERC20Basic {
              function allowance(address owner, address spender)
                public view returns (uint256);
            
              function transferFrom(address from, address to, uint256 value)
                public returns (bool);
            
              function approve(address spender, uint256 value) public returns (bool);
              event Approval(
                address indexed owner,
                address indexed spender,
                uint256 value
              );
            }
            
            contract TokenRecipient {
                event ReceivedEther(address indexed sender, uint amount);
                event ReceivedTokens(address indexed from, uint256 value, address indexed token, bytes extraData);
            
                /**
                 * @dev Receive tokens and generate a log event
                 * @param from Address from which to transfer tokens
                 * @param value Amount of tokens to transfer
                 * @param token Address of token
                 * @param extraData Additional data to log
                 */
                function receiveApproval(address from, uint256 value, address token, bytes extraData) public {
                    ERC20 t = ERC20(token);
                    require(t.transferFrom(from, this, value));
                    emit ReceivedTokens(from, value, token, extraData);
                }
            
                /**
                 * @dev Receive Ether and generate a log event
                 */
                function () payable public {
                    emit ReceivedEther(msg.sender, msg.value);
                }
            }
            
            contract ProxyRegistry is Ownable {
            
                /* DelegateProxy implementation contract. Must be initialized. */
                address public delegateProxyImplementation;
            
                /* Authenticated proxies by user. */
                mapping(address => OwnableDelegateProxy) public proxies;
            
                /* Contracts pending access. */
                mapping(address => uint) public pending;
            
                /* Contracts allowed to call those proxies. */
                mapping(address => bool) public contracts;
            
                /* Delay period for adding an authenticated contract.
                   This mitigates a particular class of potential attack on the Wyvern DAO (which owns this registry) - if at any point the value of assets held by proxy contracts exceeded the value of half the WYV supply (votes in the DAO),
                   a malicious but rational attacker could buy half the Wyvern and grant themselves access to all the proxy contracts. A delay period renders this attack nonthreatening - given two weeks, if that happened, users would have
                   plenty of time to notice and transfer their assets.
                */
                uint public DELAY_PERIOD = 2 weeks;
            
                /**
                 * Start the process to enable access for specified contract. Subject to delay period.
                 *
                 * @dev ProxyRegistry owner only
                 * @param addr Address to which to grant permissions
                 */
                function startGrantAuthentication (address addr)
                    public
                    onlyOwner
                {
                    require(!contracts[addr] && pending[addr] == 0);
                    pending[addr] = now;
                }
            
                /**
                 * End the process to nable access for specified contract after delay period has passed.
                 *
                 * @dev ProxyRegistry owner only
                 * @param addr Address to which to grant permissions
                 */
                function endGrantAuthentication (address addr)
                    public
                    onlyOwner
                {
                    require(!contracts[addr] && pending[addr] != 0 && ((pending[addr] + DELAY_PERIOD) < now));
                    pending[addr] = 0;
                    contracts[addr] = true;
                }
            
                /**
                 * Revoke access for specified contract. Can be done instantly.
                 *
                 * @dev ProxyRegistry owner only
                 * @param addr Address of which to revoke permissions
                 */    
                function revokeAuthentication (address addr)
                    public
                    onlyOwner
                {
                    contracts[addr] = false;
                }
            
                /**
                 * Register a proxy contract with this registry
                 *
                 * @dev Must be called by the user which the proxy is for, creates a new AuthenticatedProxy
                 * @return New AuthenticatedProxy contract
                 */
                function registerProxy()
                    public
                    returns (OwnableDelegateProxy proxy)
                {
                    require(proxies[msg.sender] == address(0));
                    proxy = new OwnableDelegateProxy(msg.sender, delegateProxyImplementation, abi.encodeWithSignature("initialize(address,address)", msg.sender, address(this)));
                    proxies[msg.sender] = proxy;
                    return proxy;
                }
            
            }
            
            contract WyvernProxyRegistry is ProxyRegistry {
            
                string public constant name = "Project Wyvern Proxy Registry";
            
                /* Whether the initial auth address has been set. */
                bool public initialAddressSet = false;
            
                constructor ()
                    public
                {
                    delegateProxyImplementation = new AuthenticatedProxy();
                }
            
                /** 
                 * Grant authentication to the initial Exchange protocol contract
                 *
                 * @dev No delay, can only be called once - after that the standard registry process with a delay must be used
                 * @param authAddress Address of the contract to grant authentication
                 */
                function grantInitialAuthentication (address authAddress)
                    onlyOwner
                    public
                {
                    require(!initialAddressSet);
                    initialAddressSet = true;
                    contracts[authAddress] = true;
                }
            
            }
            
            contract OwnedUpgradeabilityStorage {
            
              // Current implementation
              address internal _implementation;
            
              // Owner of the contract
              address private _upgradeabilityOwner;
            
              /**
               * @dev Tells the address of the owner
               * @return the address of the owner
               */
              function upgradeabilityOwner() public view returns (address) {
                return _upgradeabilityOwner;
              }
            
              /**
               * @dev Sets the address of the owner
               */
              function setUpgradeabilityOwner(address newUpgradeabilityOwner) internal {
                _upgradeabilityOwner = newUpgradeabilityOwner;
              }
            
              /**
              * @dev Tells the address of the current implementation
              * @return address of the current implementation
              */
              function implementation() public view returns (address) {
                return _implementation;
              }
            
              /**
              * @dev Tells the proxy type (EIP 897)
              * @return Proxy type, 2 for forwarding proxy
              */
              function proxyType() public pure returns (uint256 proxyTypeId) {
                return 2;
              }
            }
            
            contract AuthenticatedProxy is TokenRecipient, OwnedUpgradeabilityStorage {
            
                /* Whether initialized. */
                bool initialized = false;
            
                /* Address which owns this proxy. */
                address public user;
            
                /* Associated registry with contract authentication information. */
                ProxyRegistry public registry;
            
                /* Whether access has been revoked. */
                bool public revoked;
            
                /* Delegate call could be used to atomically transfer multiple assets owned by the proxy contract with one order. */
                enum HowToCall { Call, DelegateCall }
            
                /* Event fired when the proxy access is revoked or unrevoked. */
                event Revoked(bool revoked);
            
                /**
                 * Initialize an AuthenticatedProxy
                 *
                 * @param addrUser Address of user on whose behalf this proxy will act
                 * @param addrRegistry Address of ProxyRegistry contract which will manage this proxy
                 */
                function initialize (address addrUser, ProxyRegistry addrRegistry)
                    public
                {
                    require(!initialized);
                    initialized = true;
                    user = addrUser;
                    registry = addrRegistry;
                }
            
                /**
                 * Set the revoked flag (allows a user to revoke ProxyRegistry access)
                 *
                 * @dev Can be called by the user only
                 * @param revoke Whether or not to revoke access
                 */
                function setRevoke(bool revoke)
                    public
                {
                    require(msg.sender == user);
                    revoked = revoke;
                    emit Revoked(revoke);
                }
            
                /**
                 * Execute a message call from the proxy contract
                 *
                 * @dev Can be called by the user, or by a contract authorized by the registry as long as the user has not revoked access
                 * @param dest Address to which the call will be sent
                 * @param howToCall Which kind of call to make
                 * @param calldata Calldata to send
                 * @return Result of the call (success or failure)
                 */
                function proxy(address dest, HowToCall howToCall, bytes calldata)
                    public
                    returns (bool result)
                {
                    require(msg.sender == user || (!revoked && registry.contracts(msg.sender)));
                    if (howToCall == HowToCall.Call) {
                        result = dest.call(calldata);
                    } else if (howToCall == HowToCall.DelegateCall) {
                        result = dest.delegatecall(calldata);
                    }
                    return result;
                }
            
                /**
                 * Execute a message call and assert success
                 * 
                 * @dev Same functionality as `proxy`, just asserts the return value
                 * @param dest Address to which the call will be sent
                 * @param howToCall What kind of call to make
                 * @param calldata Calldata to send
                 */
                function proxyAssert(address dest, HowToCall howToCall, bytes calldata)
                    public
                {
                    require(proxy(dest, howToCall, calldata));
                }
            
            }
            
            contract Proxy {
            
              /**
              * @dev Tells the address of the implementation where every call will be delegated.
              * @return address of the implementation to which it will be delegated
              */
              function implementation() public view returns (address);
            
              /**
              * @dev Tells the type of proxy (EIP 897)
              * @return Type of proxy, 2 for upgradeable proxy
              */
              function proxyType() public pure returns (uint256 proxyTypeId);
            
              /**
              * @dev Fallback function allowing to perform a delegatecall to the given implementation.
              * This function will return whatever the implementation call returns
              */
              function () payable public {
                address _impl = implementation();
                require(_impl != address(0));
            
                assembly {
                  let ptr := mload(0x40)
                  calldatacopy(ptr, 0, calldatasize)
                  let result := delegatecall(gas, _impl, ptr, calldatasize, 0, 0)
                  let size := returndatasize
                  returndatacopy(ptr, 0, size)
            
                  switch result
                  case 0 { revert(ptr, size) }
                  default { return(ptr, size) }
                }
              }
            }
            
            contract OwnedUpgradeabilityProxy is Proxy, OwnedUpgradeabilityStorage {
              /**
              * @dev Event to show ownership has been transferred
              * @param previousOwner representing the address of the previous owner
              * @param newOwner representing the address of the new owner
              */
              event ProxyOwnershipTransferred(address previousOwner, address newOwner);
            
              /**
              * @dev This event will be emitted every time the implementation gets upgraded
              * @param implementation representing the address of the upgraded implementation
              */
              event Upgraded(address indexed implementation);
            
              /**
              * @dev Upgrades the implementation address
              * @param implementation representing the address of the new implementation to be set
              */
              function _upgradeTo(address implementation) internal {
                require(_implementation != implementation);
                _implementation = implementation;
                emit Upgraded(implementation);
              }
            
              /**
              * @dev Throws if called by any account other than the owner.
              */
              modifier onlyProxyOwner() {
                require(msg.sender == proxyOwner());
                _;
              }
            
              /**
               * @dev Tells the address of the proxy owner
               * @return the address of the proxy owner
               */
              function proxyOwner() public view returns (address) {
                return upgradeabilityOwner();
              }
            
              /**
               * @dev Allows the current owner to transfer control of the contract to a newOwner.
               * @param newOwner The address to transfer ownership to.
               */
              function transferProxyOwnership(address newOwner) public onlyProxyOwner {
                require(newOwner != address(0));
                emit ProxyOwnershipTransferred(proxyOwner(), newOwner);
                setUpgradeabilityOwner(newOwner);
              }
            
              /**
               * @dev Allows the upgradeability owner to upgrade the current implementation of the proxy.
               * @param implementation representing the address of the new implementation to be set.
               */
              function upgradeTo(address implementation) public onlyProxyOwner {
                _upgradeTo(implementation);
              }
            
              /**
               * @dev Allows the upgradeability owner to upgrade the current implementation of the proxy
               * and delegatecall the new implementation for initialization.
               * @param implementation representing the address of the new implementation to be set.
               * @param data represents the msg.data to bet sent in the low level call. This parameter may include the function
               * signature of the implementation to be called with the needed payload
               */
              function upgradeToAndCall(address implementation, bytes data) payable public onlyProxyOwner {
                upgradeTo(implementation);
                require(address(this).delegatecall(data));
              }
            }
            
            contract OwnableDelegateProxy is OwnedUpgradeabilityProxy {
            
                constructor(address owner, address initialImplementation, bytes calldata)
                    public
                {
                    setUpgradeabilityOwner(owner);
                    _upgradeTo(initialImplementation);
                    require(initialImplementation.delegatecall(calldata));
                }
            
            }