Cryo Explorer Ethereum Mainnet

Address Contract Verified

Address 0xAfD759C7356053D6CCBE6d416D4F3b66C6eA6bE3
Balance 0 ETH
Nonce 38
Code Size 8070 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

8070 bytes
0x60806040523480156200001157600080fd5b50600436106200014e5760003560e01c80638da5cb5b11620000c0578063dcfa9222116200008b578063e71a02e1116200006e578063e71a02e1146200034c578063ef7f38341462000356578063f2fde38b146200036d57600080fd5b8063dcfa9222146200032b578063ddd81f82146200034257600080fd5b80638da5cb5b146200029b57806397204d8e14620002ba578063c455279114620002db578063d4e8e063146200031457600080fd5b806353376d1f116200011e578063631d9e3f1162000101578063631d9e3f146200026157806369dc9ff3146200026b578063715018a6146200029157600080fd5b806353376d1f14620002185780635eebea20146200022f57600080fd5b8062686741146200015357806306fdde0314620001945780631a86ac4f14620001e057806338b6e40714620001ff575b600080fd5b6200016a62000164366004620010e9565b62000384565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620001d16040518060400160405280601e81526020017f57797665726e2050726f746f636f6c2050726f7879205265676973747279000081525081565b6040516200018b91906200117c565b600654620001ee9060ff1681565b60405190151581526020016200018b565b6200021662000210366004620010e9565b62000551565b005b6200021662000229366004620010e9565b6200077f565b6200025262000240366004620010e9565b60036020526000908152604090205481565b6040519081526020016200018b565b6200016a6200084e565b620001ee6200027c366004620010e9565b60046020526000908152604090205460ff1681565b6200021662000983565b60005473ffffffffffffffffffffffffffffffffffffffff166200016a565b6001546200016a9073ffffffffffffffffffffffffffffffffffffffff1681565b6200016a620002ec366004620010e9565b60026020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6200021662000325366004620010e9565b62000a14565b620002166200033c36600462001191565b62000ba8565b6200016a62000d7c565b6200025260055481565b6200021662000367366004620010e9565b62000d8e565b620002166200037e366004620010e9565b62000f06565b73ffffffffffffffffffffffffffffffffffffffff818116600090815260026020526040812054909116156200041b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f5573657220616c72656164792068617320612070726f7879000000000000000060448201526064015b60405180910390fd5b60015460405173ffffffffffffffffffffffffffffffffffffffff808516602483015230604483015284921690606401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f485cc9550000000000000000000000000000000000000000000000000000000017905251620004cd90620010b1565b620004db93929190620011c9565b604051809103906000f080158015620004f8573d6000803e3d6000fd5b5073ffffffffffffffffffffffffffffffffffffffff928316600090815260026020526040902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016938216939093179092555090565b60005473ffffffffffffffffffffffffffffffffffffffff163314620005d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000412565b73ffffffffffffffffffffffffffffffffffffffff811660009081526004602052604090205460ff161580156200062f575073ffffffffffffffffffffffffffffffffffffffff811660009081526003602052604090205415155b80156200066f575060055473ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604090205442916200066d916200120d565b105b62000723576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604660248201527f436f6e7472616374206973206e6f206c6f6e6765722070656e64696e67206f7260448201527f2068617320616c7265616479206265656e20617070726f76656420627920726560648201527f6769737472790000000000000000000000000000000000000000000000000000608482015260a40162000412565b73ffffffffffffffffffffffffffffffffffffffff1660009081526003602090815260408083208390556004909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b60005473ffffffffffffffffffffffffffffffffffffffff16331462000802576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000412565b73ffffffffffffffffffffffffffffffffffffffff16600090815260046020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055565b6001546040513360248201819052306044830152600092909173ffffffffffffffffffffffffffffffffffffffff90911690606401604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f485cc95500000000000000000000000000000000000000000000000000000000179052516200090590620010b1565b6200091393929190620011c9565b604051809103906000f08015801562000930573d6000803e3d6000fd5b5033600090815260026020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8316179055919050565b60005473ffffffffffffffffffffffffffffffffffffffff16331462000a06576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000412565b62000a1260006200103c565b565b60005473ffffffffffffffffffffffffffffffffffffffff16331462000a97576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000412565b73ffffffffffffffffffffffffffffffffffffffff811660009081526004602052604090205460ff1615801562000af1575073ffffffffffffffffffffffffffffffffffffffff8116600090815260036020526040902054155b62000b7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603360248201527f436f6e747261637420697320616c726561647920616c6c6f77656420696e207260448201527f656769737472792c206f722070656e64696e6700000000000000000000000000606482015260840162000412565b73ffffffffffffffffffffffffffffffffffffffff166000908152600360205260409020429055565b73ffffffffffffffffffffffffffffffffffffffff8083166000908152600260205260409020541633811462000c61576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f50726f7879207472616e736665722063616e206f6e6c792062652063616c6c6560448201527f64206279207468652070726f7879000000000000000000000000000000000000606482015260840162000412565b73ffffffffffffffffffffffffffffffffffffffff828116600090815260026020526040902054161562000d18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f50726f7879207472616e7366657220686173206578697374696e672070726f7860448201527f792061732064657374696e6174696f6e00000000000000000000000000000000606482015260840162000412565b73ffffffffffffffffffffffffffffffffffffffff92831660009081526002602052604080822080547fffffffffffffffffffffffff0000000000000000000000000000000000000000908116909155938516825290208054919093169116179055565b600062000d893362000384565b905090565b60005473ffffffffffffffffffffffffffffffffffffffff16331462000e11576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000412565b60065460ff161562000ea6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f57797665726e2050726f746f636f6c2050726f7879205265676973747279206960448201527f6e697469616c206164647265737320616c726561647920736574000000000000606482015260840162000412565b600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00908116600190811790925573ffffffffffffffffffffffffffffffffffffffff90921660009081526004602052604090208054909216179055565b60005473ffffffffffffffffffffffffffffffffffffffff16331462000f89576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000412565b73ffffffffffffffffffffffffffffffffffffffff81166200102e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840162000412565b62001039816200103c565b50565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b610d03806200124e83390190565b803573ffffffffffffffffffffffffffffffffffffffff81168114620010e457600080fd5b919050565b600060208284031215620010fc57600080fd5b6200110782620010bf565b9392505050565b6000815180845260005b81811015620011365760208185018101518683018201520162001118565b8181111562001149576000602083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006200110760208301846200110e565b60008060408385031215620011a557600080fd5b620011b083620010bf565b9150620011c060208401620010bf565b90509250929050565b600073ffffffffffffffffffffffffffffffffffffffff8086168352808516602084015250606060408301526200120460608301846200110e565b95945050505050565b6000821982111562001248577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b50019056fe60806040523480156200001157600080fd5b5060405162000d0338038062000d03833981016040819052620000349162000248565b600180546001600160a01b0319166001600160a01b0385161790556200005a826200012c565b6000826001600160a01b03168260405162000076919062000328565b600060405180830381855af49150503d8060008114620000b3576040519150601f19603f3d011682016040523d82523d6000602084013e620000b8565b606091505b5050905080620001225760405162461bcd60e51b815260206004820152602a60248201527f4f776e61626c6544656c656761746550726f7879206661696c656420696d706c60448201526932b6b2b73a30ba34b7b760b11b60648201526084015b60405180910390fd5b5050505062000346565b6000546001600160a01b038083169116036200019a5760405162461bcd60e51b815260206004820152602660248201527f50726f787920616c72656164792075736573207468697320696d706c656d656e6044820152653a30ba34b7b760d11b606482015260840162000119565b600080546001600160a01b0319166001600160a01b038316908117825560405190917fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b91a250565b80516001600160a01b0381168114620001fa57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200023257818101518382015260200162000218565b8381111562000242576000848401525b50505050565b6000806000606084860312156200025e57600080fd5b6200026984620001e2565b92506200027960208501620001e2565b60408501519092506001600160401b03808211156200029757600080fd5b818601915086601f830112620002ac57600080fd5b815181811115620002c157620002c1620001ff565b604051601f8201601f19908116603f01168101908382118183101715620002ec57620002ec620001ff565b816040528281528960208487010111156200030657600080fd5b6200031983602083016020880162000215565b80955050505050509250925092565b600082516200033c81846020870162000215565b9190910192915050565b6109ad80620003566000396000f3fe6080604052600436106100695760003560e01c80635c60da1b116100435780635c60da1b146100f15780636fde82021461011c578063f1739cae1461014757610078565b8063025313a2146100805780633659cfe6146100be5780634f1ef286146100de57610078565b3661007857610076610167565b005b610076610167565b34801561008c57600080fd5b50610095610190565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100ca57600080fd5b506100766100d936600461080b565b6101b6565b6100766100ec36600461085c565b610289565b3480156100fd57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610095565b34801561012857600080fd5b5060015473ffffffffffffffffffffffffffffffffffffffff16610095565b34801561015357600080fd5b5061007661016236600461080b565b61042b565b61018e61018960005473ffffffffffffffffffffffffffffffffffffffff1690565b61062a565b565b60006101b160015473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b6101be610190565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461027d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f6e6c79207468652070726f7879206f776e65722063616e2063616c6c20746860448201527f6973206d6574686f64000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b610286816106cb565b50565b610291610190565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461034b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f6e6c79207468652070726f7879206f776e65722063616e2063616c6c20746860448201527f6973206d6574686f6400000000000000000000000000000000000000000000006064820152608401610274565b610354826101b6565b60003073ffffffffffffffffffffffffffffffffffffffff168260405161037b919061093c565b600060405180830381855af49150503d80600081146103b6576040519150601f19603f3d011682016040523d82523d6000602084013e6103bb565b606091505b5050905080610426576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f43616c6c206661696c65642061667465722070726f78792075706772616465006044820152606401610274565b505050565b610433610190565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146104ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4f6e6c79207468652070726f7879206f776e65722063616e2063616c6c20746860448201527f6973206d6574686f6400000000000000000000000000000000000000000000006064820152608401610274565b73ffffffffffffffffffffffffffffffffffffffff811661058f576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f4e6577206f776e65722063616e6e6f7420626520746865206e756c6c2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610274565b7f5a3e66efaa1e445ebd894728a69d6959842ea1e97bd79b892797106e270efcd96105b8610190565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a1600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff831617905550565b73ffffffffffffffffffffffffffffffffffffffff81166106a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f50726f787920696d706c656d656e746174696f6e2072657175697265640000006044820152606401610274565b3660008037600080366000845af43d6000803e8080156106c6573d6000f35b3d6000fd5b60005473ffffffffffffffffffffffffffffffffffffffff808316911603610775576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f50726f787920616c72656164792075736573207468697320696d706c656d656e60448201527f746174696f6e00000000000000000000000000000000000000000000000000006064820152608401610274565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8316908117825560405190917fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b91a250565b803573ffffffffffffffffffffffffffffffffffffffff8116811461080657600080fd5b919050565b60006020828403121561081d57600080fd5b610826826107e2565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806040838503121561086f57600080fd5b610878836107e2565b9150602083013567ffffffffffffffff8082111561089557600080fd5b818501915085601f8301126108a957600080fd5b8135818111156108bb576108bb61082d565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156109015761090161082d565b8160405282815288602084870101111561091a57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b6000825160005b8181101561095d5760208186018101518583015201610943565b8181111561096c576000828501525b50919091019291505056fea2646970667358221220574f03fcb1646c176cff390c3e96bcd8f8a7bba2e8d74afbb0e71986ca82361464736f6c634300080e0033a2646970667358221220aaa82ababa29263ac4b9c81728c925d6b271baa820c61443d337772e42d3861a64736f6c634300080e0033

Verified Source Code Full Match

Compiler: v0.8.14+commit.80d49f37 EVM: london Optimization: Yes (1000000 runs)
WyvernRegistry.sol 38 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.14;

import "./registry/ProxyRegistry.sol";
import "./registry/AuthenticatedProxy.sol";

/**
 * @title WyvernRegistry
 * @author Wyvern Protocol Developers
 */
contract WyvernRegistry is ProxyRegistry {
    string public constant name = "Wyvern Protocol Proxy Registry";

    /* Whether the initial auth address has been set. */
    bool public initialAddressSet = false;

    constructor() {
        AuthenticatedProxy impl = new AuthenticatedProxy();
        impl.initialize(address(this), this);
        impl.setRevoke(true);
        delegateProxyImplementation = address(impl);
    }

    /**
     * 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) public onlyOwner {
        require(
            !initialAddressSet,
            "Wyvern Protocol Proxy Registry initial address already set"
        );
        initialAddressSet = true;
        contracts[authAddress] = true;
    }
}
Proxy.sol 85 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.14;

/**
 * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
 * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
 * be specified by overriding the virtual {implementation} function.
 *
 * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
 * different contract through the {_delegate} function.
 *
 * The success and return data of the delegated call will be returned back to the caller of the proxy.
 */
abstract contract Proxy {
    /**
     * @dev Delegates the current call to `implementation`.
     *
     * This function does not return to its internal call site, it will return directly to the external caller.
     */
    function _delegate(address _impl) internal virtual {
        require(_impl != address(0), "Proxy implementation required");
        assembly {
            // Copy msg.data. We take full control of memory in this inline assembly
            // block because it will not return to Solidity code. We overwrite the
            // Solidity scratch pad at memory position 0.
            calldatacopy(0, 0, calldatasize())

            // Call the implementation.
            // out and outsize are 0 because we don't know the size yet.
            let result := delegatecall(gas(), _impl, 0, calldatasize(), 0, 0)

            // Copy the returned data.
            returndatacopy(0, 0, returndatasize())

            switch result
            // delegatecall returns 0 on error.
            case 0 {
                revert(0, returndatasize())
            }
            default {
                return(0, returndatasize())
            }
        }
    }

    /**
     * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function
     * and {_fallback} should delegate.
     */
    function implementation() public view virtual returns (address);

    /**
     * @dev Delegates the current call to the address returned by `implementation()`.
     *
     * This function does not return to its internal call site, it will return directly to the external caller.
     */
    function _fallback() internal virtual {
        _beforeFallback();
        _delegate(implementation());
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `implementation()`. Will run if no other
     * function in the contract matches the call data.
     */
    fallback() external payable virtual {
        _fallback();
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `implementation()`. Will run if call data
     * is empty.
     */
    receive() external payable virtual {
        _fallback();
    }

    /**
     * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
     * call, or as part of the Solidity `fallback` or `receive` functions.
     *
     * If overridden should call `super._beforeFallback()`.
     */
    function _beforeFallback() internal virtual {}
}
ProxyRegistry.sol 157 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.14;

import "@openzeppelin/contracts/access/Ownable.sol";

import "./OwnableDelegateProxy.sol";
import "./ProxyRegistryInterface.sol";

/**
 * @title ProxyRegistry
 * @author Wyvern Protocol Developers
 * @notice
 * Proxy registry; keeps a mapping of AuthenticatedProxy contracts and mapping of contracts authorized to access them.
 * Abstracted away from the Exchange (a) to reduce Exchange attack surface and (b) so that the Exchange contract can be upgraded without users needing to transfer assets to new proxies.
 */
contract ProxyRegistry is Ownable, ProxyRegistryInterface {
    /* DelegateProxy implementation contract. Must be initialized. */
    address public override delegateProxyImplementation;

    /* Authenticated proxies by user. */
    mapping(address => OwnableDelegateProxy) public override proxies;

    /* Contracts pending access. */
    mapping(address => uint256) 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.
    */
    uint256 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,
            "Contract is already allowed in registry, or pending"
        );
        pending[addr] = block.timestamp;
    }

    /**
     * End the process to enable 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) < block.timestamp),
            "Contract is no longer pending or has already been approved by registry"
        );
        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 proxy New AuthenticatedProxy contract
     */
    function registerProxy() public returns (OwnableDelegateProxy proxy) {
        return registerProxyFor(msg.sender);
    }

    /**
     * Register a proxy contract with this registry, overriding any existing proxy
     *
     * @dev Must be called by the user which the proxy is for, creates a new AuthenticatedProxy
     * @return proxy New AuthenticatedProxy contract
     */
    function registerProxyOverride()
        public
        returns (OwnableDelegateProxy proxy)
    {
        proxy = new OwnableDelegateProxy(
            msg.sender,
            delegateProxyImplementation,
            abi.encodeWithSignature(
                "initialize(address,address)",
                msg.sender,
                address(this)
            )
        );
        proxies[msg.sender] = proxy;
        return proxy;
    }

    /**
     * Register a proxy contract with this registry
     *
     * @dev Can be called by any user
     * @return proxy New AuthenticatedProxy contract
     */
    function registerProxyFor(address user)
        public
        returns (OwnableDelegateProxy proxy)
    {
        require(
            proxies[user] == OwnableDelegateProxy(payable(0)),
            "User already has a proxy"
        );
        proxy = new OwnableDelegateProxy(
            user,
            delegateProxyImplementation,
            abi.encodeWithSignature(
                "initialize(address,address)",
                user,
                address(this)
            )
        );
        proxies[user] = proxy;
        return proxy;
    }

    /**
     * Transfer access
     */
    function transferAccessTo(address from, address to) public {
        OwnableDelegateProxy proxy = proxies[from];

        /* CHECKS */
        require(
            OwnableDelegateProxy(payable(msg.sender)) == proxy,
            "Proxy transfer can only be called by the proxy"
        );
        require(
            proxies[to] == OwnableDelegateProxy(payable(0)),
            "Proxy transfer has existing proxy as destination"
        );

        /* EFFECTS */
        delete proxies[from];
        proxies[to] = proxy;
    }
}
TokenRecipient.sol 47 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.14;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

/**
 * @title TokenRecipient
 * @author Wyvern Protocol Developers
 * @dev Modified very slightly from the example on http://ethereum.org/dao (just to index log parameters).
 */
contract TokenRecipient {
    event ReceivedEther(address indexed sender, uint256 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 memory extraData
    ) public {
        ERC20 t = ERC20(token);
        require(
            t.transferFrom(from, address(this), value),
            "ERC20 token transfer failed"
        );
        emit ReceivedTokens(from, value, token, extraData);
    }

    /**
     * @dev Receive Ether and generate a log event
     */
    receive() external payable {
        emit ReceivedEther(msg.sender, msg.value);
    }
}
Context.sol 24 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}
AuthenticatedProxy.sol 105 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.14;

import "./ProxyRegistry.sol";
import "./TokenRecipient.sol";
import "./proxy/OwnedUpgradeabilityStorage.sol";

/**
 * @title AuthenticatedProxy
 * @author Wyvern Protocol Developers
 * @dev Proxy contract to hold access to assets on behalf of a user (e.g. ERC20 approve) and execute calls under particular conditions.
 */
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, "Authenticated proxy already 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,
            "Authenticated proxy can only be revoked by its 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 data Calldata to send
     * @return result Result of the call (success or failure)
     */
    function proxy(
        address dest,
        HowToCall howToCall,
        bytes memory data
    ) public returns (bool result) {
        require(
            msg.sender == user || (!revoked && registry.contracts(msg.sender)),
            "Authenticated proxy can only be called by its user, or by a contract authorized by the registry as long as the user has not revoked access"
        );
        bytes memory ret;
        if (howToCall == HowToCall.Call) {
            (result, ret) = dest.call(data);
        } else if (howToCall == HowToCall.DelegateCall) {
            (result, ret) = dest.delegatecall(data);
        }
        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 data Calldata to send
     */
    function proxyAssert(
        address dest,
        HowToCall howToCall,
        bytes memory data
    ) public {
        require(proxy(dest, howToCall, data), "Proxy assertion failed");
    }
}
Ownable.sol 76 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}
OwnableDelegateProxy.sol 21 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.14;

import "./proxy/OwnedUpgradeabilityProxy.sol";

/**
 * @title OwnableDelegateProxy
 * @author Wyvern Protocol Developers
 */
contract OwnableDelegateProxy is OwnedUpgradeabilityProxy {
    constructor(
        address owner,
        address initialImplementation,
        bytes memory data
    ) {
        setUpgradeabilityOwner(owner);
        _upgradeTo(initialImplementation);
        (bool success, ) = initialImplementation.delegatecall(data);
        require(success, "OwnableDelegateProxy failed implementation");
    }
}
ERC20.sol 383 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.0;

import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

    mapping(address => mapping(address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * The default value of {decimals} is 18. To select a different value for
     * {decimals} you should overload it.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override returns (string memory) {
        return _symbol;
    }

    /**
     * @dev Returns the number of decimals used to get its user representation.
     * For example, if `decimals` equals `2`, a balance of `505` tokens should
     * be displayed to a user as `5.05` (`505 / 10 ** 2`).
     *
     * Tokens usually opt for a value of 18, imitating the relationship between
     * Ether and Wei. This is the value {ERC20} uses, unless this function is
     * overridden;
     *
     * NOTE: This information is only used for _display_ purposes: it in
     * no way affects any of the arithmetic of the contract, including
     * {IERC20-balanceOf} and {IERC20-transfer}.
     */
    function decimals() public view virtual override returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual override returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address to, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, amount);
        return true;
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
     * `transferFrom`. This is semantically equivalent to an infinite approval.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * NOTE: Does not update the allowance if the current allowance
     * is the maximum `uint256`.
     *
     * Requirements:
     *
     * - `from` and `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `amount`.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual override returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, amount);
        _transfer(from, to, amount);
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, allowance(owner, spender) + addedValue);
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        address owner = _msgSender();
        uint256 currentAllowance = allowance(owner, spender);
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(owner, spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    /**
     * @dev Moves `amount` of tokens from `sender` to `recipient`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     */
    function _transfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(from, to, amount);

        uint256 fromBalance = _balances[from];
        require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[from] = fromBalance - amount;
        }
        _balances[to] += amount;

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        _balances[account] += amount;
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
        }
        _totalSupply -= amount;

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

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

    /**
     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.
     *
     * Does not update the allowance amount in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Might emit an {Approval} event.
     */
    function _spendAllowance(
        address owner,
        address spender,
        uint256 amount
    ) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            require(currentAllowance >= amount, "ERC20: insufficient allowance");
            unchecked {
                _approve(owner, spender, currentAllowance - amount);
            }
        }
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * has been transferred to `to`.
     * - when `from` is zero, `amount` tokens have been minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal virtual {}
}
ProxyRegistryInterface.sol 14 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.14;

import "./OwnableDelegateProxy.sol";

/**
 * @title ProxyRegistryInterface
 * @author Wyvern Protocol Developers
 */
interface ProxyRegistryInterface {
    function delegateProxyImplementation() external returns (address);

    function proxies(address owner) external returns (OwnableDelegateProxy);
}
IERC20.sol 82 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}
OwnedUpgradeabilityProxy.sol 99 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.14;

import "./Proxy.sol";
import "./OwnedUpgradeabilityStorage.sol";

/**
 * @title OwnedUpgradeabilityProxy
 * @dev This contract combines an upgradeability proxy with basic authorization control functionalities
 */
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 Tells the address of the current implementation
     * @return address of the current implementation
     */
    function implementation() public view override returns (address) {
        return _implementation;
    }

    /**
     * @dev Upgrades the implementation address
     * @param _impl representing the address of the new implementation to be set
     */
    function _upgradeTo(address _impl) internal {
        require(
            _implementation != _impl,
            "Proxy already uses this implementation"
        );
        _implementation = _impl;
        emit Upgraded(_impl);
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyProxyOwner() {
        require(
            msg.sender == proxyOwner(),
            "Only the proxy owner can call this method"
        );
        _;
    }

    /**
     * @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), "New owner cannot be the null address");
        emit ProxyOwnershipTransferred(proxyOwner(), newOwner);
        setUpgradeabilityOwner(newOwner);
    }

    /**
     * @dev Allows the upgradeability owner to upgrade the current implementation of the proxy.
     * @param _impl representing the address of the new implementation to be set.
     */
    function upgradeTo(address _impl) public onlyProxyOwner {
        _upgradeTo(_impl);
    }

    /**
     * @dev Allows the upgradeability owner to upgrade the current implementation of the proxy
     * and delegatecall the new implementation for initialization.
     * @param _impl 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 _impl, bytes memory data)
        public
        payable
        onlyProxyOwner
    {
        upgradeTo(_impl);
        (bool success, ) = address(this).delegatecall(data);
        require(success, "Call failed after proxy upgrade");
    }
}
OwnedUpgradeabilityStorage.sol 29 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.14;

/**
 * @title OwnedUpgradeabilityStorage
 * @dev This contract keeps track of the upgradeability owner
 */
contract OwnedUpgradeabilityStorage {
    // Current implementation
    address internal _implementation;

    // Owner of the contract
    address private _upgradeabilityOwner;

    /**
     * @dev Tells the address of the owner
     * @return address 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;
    }
}
IERC20Metadata.sol 28 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

Read Contract

DELAY_PERIOD 0xe71a02e1 → uint256
contracts 0x69dc9ff3 → bool
delegateProxyImplementation 0x97204d8e → address
initialAddressSet 0x1a86ac4f → bool
name 0x06fdde03 → string
owner 0x8da5cb5b → address
pending 0x5eebea20 → uint256
proxies 0xc4552791 → address

Write Contract 10 functions

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

endGrantAuthentication 0x38b6e407
address addr
grantInitialAuthentication 0xef7f3834
address authAddress
registerProxy 0xddd81f82
No parameters
returns: address
registerProxyFor 0x00686741
address user
returns: address
registerProxyOverride 0x631d9e3f
No parameters
returns: address
renounceOwnership 0x715018a6
No parameters
revokeAuthentication 0x53376d1f
address addr
startGrantAuthentication 0xd4e8e063
address addr
transferAccessTo 0xdcfa9222
address from
address to
transferOwnership 0xf2fde38b
address newOwner

Recent Transactions

No transactions found for this address