Cryo Explorer Ethereum Mainnet

Address Contract Partially Verified

Address 0xF54b696180903B8F3a1CaE532e5328ed0dfFA4CC
Balance 0.006907 ETH
Nonce 1
Code Size 6454 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

6454 bytes
0x608060405260043610610134575f3560e01c8063806ad57e116100a8578063c4f987a51161006d578063c4f987a5146103bf578063c5b3ffe9146103de578063d239c97314610409578063e6adfe3714610428578063efd00e8a14610447578063fc82f0841461044f575f80fd5b8063806ad57e14610315578063877f210c14610334578063983c45cf14610353578063aa15664514610372578063c3170007146103a0575f80fd5b80634460d3cf116100f95780634460d3cf1461024657806345e0e412146102655780635af2e9fb146102845780635eae21fa146102a357806368c4ac26146102c2578063799bf3f914610300575f80fd5b80630a0f8168146101695780630c53c51c146101a457806321507b4e146101c457806327d7874c146101e35780632d0335ab14610204575f80fd5b366101655760405134907f5e168818916f1fd9e52c6751cc95b7117e0d0e2d5d4f3868f21ce415555b9b40905f90a2005b5f80fd5b348015610174575f80fd5b505f54610187906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6101b76101b2366004611402565b610463565b60405161019b919061152d565b3480156101cf575f80fd5b50600554610187906001600160a01b031681565b3480156101ee575f80fd5b506102026101fd366004611546565b610619565b005b34801561020f575f80fd5b5061023861021e366004611546565b6001600160a01b03165f9081526003602052604090205490565b60405190815260200161019b565b348015610251575f80fd5b50610202610260366004611546565b6106be565b348015610270575f80fd5b5061020261027f36600461155f565b610703565b34801561028f575f80fd5b5061020261029e366004611546565b6107f7565b3480156102ae575f80fd5b506102026102bd366004611594565b610842565b3480156102cd575f80fd5b506102f06102dc366004611546565b60066020525f908152604090205460ff1681565b604051901515815260200161019b565b34801561030b575f80fd5b5061023860045481565b348015610320575f80fd5b5061020261032f366004611546565b610895565b34801561033f575f80fd5b5061020261034e3660046115c9565b6108ca565b34801561035e575f80fd5b5061020261036d366004611602565b610a2b565b34801561037d575f80fd5b506102f061038c366004611546565b60016020525f908152604090205460ff1681565b3480156103ab575f80fd5b506102026103ba366004611619565b610a59565b3480156103ca575f80fd5b506102026103d9366004611546565b610ad8565b3480156103e9575f80fd5b506102386103f8366004611546565b60076020525f908152604090205481565b348015610414575f80fd5b506102f0610423366004611546565b610b0a565b348015610433575f80fd5b50610202610442366004611619565b610b3a565b610202610bb4565b34801561045a575f80fd5b50610202610c54565b60408051606081810183526001600160a01b0388165f81815260036020908152908590205484528301529181018690526104a08782878787610cf5565b6104c55760405162461bcd60e51b81526004016104bc90611688565b60405180910390fd5b6001600160a01b0387165f908152600360205260409020546104e89060016116e4565b6001600160a01b0388165f90815260036020908152604080832093909355915190918291309161051c918b918d91016116f7565b60408051601f19818403018152908290526105369161172d565b5f604051808303815f865af19150503d805f811461056f576040519150601f19603f3d011682016040523d82523d5f602084013e610574565b606091505b5091509150816105d25760405162461bcd60e51b815260206004820152602360248201527f4549503731324d6574615472616e73616374696f6e3a20494e56414c49445f4360448201526210531360ea1b60648201526084016104bc565b7f5845892132946850460bff5a0083f71031bc5bf9aadcd40f1de79423eac9b10b89338a60405161060593929190611748565b60405180910390a198975050505050505050565b806001600160a01b0381166106405760405162461bcd60e51b81526004016104bc9061177c565b5f546001600160a01b031633146106695760405162461bcd60e51b81526004016104bc906117b3565b5f80546001600160a01b0319166001600160a01b0384169081179091556040519081527ff97cbb4246b709036319093e5ff31674b9f6759076d153e1bea1f60392170fc0906020015b60405180910390a15050565b5f546001600160a01b031633146106e75760405162461bcd60e51b81526004016104bc906117b3565b5f6106f28230610da9565b90506106ff823383610e9d565b5050565b3361070d81610b0a565b6107295760405162461bcd60e51b81526004016104bc906117ea565b6001600160a01b038082165f908152600760209081526040808320439055928616825260069052205460ff166107a15760405162461bcd60e51b815260206004820152601b60248201527f546f6b656e4875623a20554e535550504f525445445f544f4b454e000000000060448201526064016104bc565b6005546107bb90849083906001600160a01b031685610fe3565b60405182906001600160a01b0385169033907fceac81a6cfb44e1614ce02f28d4c280e6e9f4c9cf2585ab625f5e182caf7023d905f90a4505050565b5f546001600160a01b031633146108205760405162461bcd60e51b81526004016104bc906117b3565b600580546001600160a01b0319166001600160a01b0392909216919091179055565b5f546001600160a01b0316331461086b5760405162461bcd60e51b81526004016104bc906117b3565b6001600160a01b03919091165f908152600660205260409020805460ff1916911515919091179055565b5f546001600160a01b031633146108be5760405162461bcd60e51b81526004016104bc906117b3565b6108c78161113a565b50565b335f9081526001602081905260409091205460ff1615151461092e5760405162461bcd60e51b815260206004820152601c60248201527f416363657373436f6e74726f6c3a20574f524b45525f44454e4945440000000060448201526064016104bc565b61093783610b0a565b6109535760405162461bcd60e51b81526004016104bc906117ea565b6001600160a01b038084165f908152600760209081526040808320439055928516825260069052205460ff166109cb5760405162461bcd60e51b815260206004820152601b60248201527f546f6b656e4875623a20554e535550504f525445445f544f4b454e000000000060448201526064016104bc565b6005546109e590839085906001600160a01b031684610fe3565b80826001600160a01b0316846001600160a01b03167fceac81a6cfb44e1614ce02f28d4c280e6e9f4c9cf2585ab625f5e182caf7023d60405160405180910390a4505050565b5f546001600160a01b03163314610a545760405162461bcd60e51b81526004016104bc906117b3565b600455565b5f546001600160a01b03163314610a825760405162461bcd60e51b81526004016104bc906117b3565b5f5b60ff8116821115610ad357610ac183838360ff16818110610aa757610aa7611821565b9050602002016020810190610abc9190611546565b61113a565b80610acb81611835565b915050610a84565b505050565b5f546001600160a01b03163314610b015760405162461bcd60e51b81526004016104bc906117b3565b6108c781611229565b6004546001600160a01b0382165f90815260076020526040812054909190610b329043611853565b101592915050565b5f546001600160a01b03163314610b635760405162461bcd60e51b81526004016104bc906117b3565b5f5b60ff8116821115610ad357610ba283838360ff16818110610b8857610b88611821565b9050602002016020810190610b9d9190611546565b611229565b80610bac81611835565b915050610b65565b33610bbe81610b0a565b610bda5760405162461bcd60e51b81526004016104bc906117ea565b6001600160a01b038082165f9081526007602052604080822043905560055490519216913480156108fc0292909190818181858888f19350505050158015610c24573d5f803e3d5ffd5b50604051349033907f2f0094ad9640858ffa87c59b7086fb03a519c627e74993edab801eb7a1503f55905f90a350565b5f546001600160a01b03163314610c7d5760405162461bcd60e51b81526004016104bc906117b3565b4780610ccb5760405162461bcd60e51b815260206004820152601a60248201527f4e6f2045746865722062616c616e636520746f2072657363756500000000000060448201526064016104bc565b604051339082156108fc029083905f818181858888f193505050501580156106ff573d5f803e3d5ffd5b5f806001610d0a610d0588611318565b611394565b604080515f8152602081018083529290925260ff861690820152606081018790526080810186905260a0016020604051602081039080840390855afa158015610d55573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b038116610d885760405162461bcd60e51b81526004016104bc90611688565b866001600160a01b0316816001600160a01b03161491505095945050505050565b604080518082018252601281527162616c616e63654f6628616464726573732960701b60209182015281516001600160a01b03848116602480840191909152845180840390910181526044909201845291810180516001600160e01b03166370a0823160e01b17905291515f928392839290871691610e279161172d565b5f604051808303815f865af19150503d805f8114610e60576040519150601f19603f3d011682016040523d82523d5f602084013e610e65565b606091505b5090925090508115155f03610e7e575f92505050610e97565b80806020019051810190610e929190611866565b925050505b92915050565b604080518082018252601981527f7472616e7366657228616464726573732c75696e74323536290000000000000060209182015281516001600160a01b0385811660248301526044808301869052845180840390910181526064909201845291810180516001600160e01b031663a9059cbb60e01b17905291515f928392871691610f28919061172d565b5f604051808303815f865af19150503d805f8114610f61576040519150601f19603f3d011682016040523d82523d5f602084013e610f66565b606091505b5091509150818015610f90575080511580610f90575080806020019051810190610f90919061187d565b610fdc5760405162461bcd60e51b815260206004820152601f60248201527f5472616e7366657248656c7065723a205452414e534645525f4641494c45440060448201526064016104bc565b5050505050565b5f80856001600160a01b03166040518060600160405280602581526020016118996025913980516020909101206040516001600160a01b038089166024830152871660448201526064810186905260840160408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051611072919061172d565b5f604051808303815f865af19150503d805f81146110ab576040519150601f19603f3d011682016040523d82523d5f602084013e6110b0565b606091505b50915091508180156110da5750805115806110da5750808060200190518101906110da919061187d565b6111325760405162461bcd60e51b8152602060048201526024808201527f5472616e7366657248656c7065723a205452414e534645525f46524f4d5f46416044820152631253115160e21b60648201526084016104bc565b505050505050565b806001600160a01b0381166111615760405162461bcd60e51b81526004016104bc9061177c565b6001600160a01b0382165f9081526001602052604090205460ff16156111d55760405162461bcd60e51b815260206004820152602360248201527f416363657373436f6e74726f6c3a20776f726b657220616c72656164792065786044820152621a5cdd60ea1b60648201526084016104bc565b6001600160a01b0382165f81815260016020818152604092839020805460ff191690921790915590519182527fb10d2a24a8c3686841e966f0c2c64c385cfaecb50a09b16aa3579bfcf3989dcd91016106b2565b806001600160a01b0381166112505760405162461bcd60e51b81526004016104bc9061177c565b6001600160a01b0382165f9081526001602081905260409091205460ff161515146112c85760405162461bcd60e51b815260206004820152602260248201527f416363657373436f6e74726f6c3a20776f726b6572206e6f7420646574656374604482015261195960f21b60648201526084016104bc565b6001600160a01b0382165f81815260016020908152604091829020805460ff1916905590519182527f6cfb0504498d3a8155a2a3dd5f41940ad5ab571197ac70f6d6948d189f6a0d2791016106b2565b5f6040518060800160405280604381526020016118be6043913980516020918201208351848301516040808701518051908601209051611377950193845260208401929092526001600160a01b03166040830152606082015260800190565b604051602081830303815290604052805190602001209050919050565b5f61139e60025490565b60405161190160f01b6020820152602281019190915260428101839052606201611377565b80356001600160a01b03811681146113d9575f80fd5b919050565b634e487b7160e01b5f52604160045260245ffd5b803560ff811681146113d9575f80fd5b5f805f805f60a08688031215611416575f80fd5b61141f866113c3565b9450602086013567ffffffffffffffff8082111561143b575f80fd5b818801915088601f83011261144e575f80fd5b813581811115611460576114606113de565b604051601f8201601f19908116603f01168101908382118183101715611488576114886113de565b816040528281528b60208487010111156114a0575f80fd5b826020860160208301375f60208483010152809850505050505060408601359250606086013591506114d4608087016113f2565b90509295509295909350565b5f5b838110156114fa5781810151838201526020016114e2565b50505f910152565b5f81518084526115198160208601602086016114e0565b601f01601f19169290920160200192915050565b602081525f61153f6020830184611502565b9392505050565b5f60208284031215611556575f80fd5b61153f826113c3565b5f8060408385031215611570575f80fd5b611579836113c3565b946020939093013593505050565b80151581146108c7575f80fd5b5f80604083850312156115a5575f80fd5b6115ae836113c3565b915060208301356115be81611587565b809150509250929050565b5f805f606084860312156115db575f80fd5b6115e4846113c3565b92506115f2602085016113c3565b9150604084013590509250925092565b5f60208284031215611612575f80fd5b5035919050565b5f806020838503121561162a575f80fd5b823567ffffffffffffffff80821115611641575f80fd5b818501915085601f830112611654575f80fd5b813581811115611662575f80fd5b8660208260051b8501011115611676575f80fd5b60209290920196919550909350505050565b60208082526028908201527f4549503731324d6574615472616e73616374696f6e3a20494e56414c49445f5360408201526749474e415455524560c01b606082015260800190565b634e487b7160e01b5f52601160045260245ffd5b80820180821115610e9757610e976116d0565b5f83516117088184602088016114e0565b60609390931b6bffffffffffffffffffffffff19169190920190815260140192915050565b5f825161173e8184602087016114e0565b9190910192915050565b6001600160a01b038481168252831660208201526060604082018190525f9061177390830184611502565b95945050505050565b6020808252601e908201527f416363657373436f6e74726f6c3a20494e56414c49445f414444524553530000604082015260600190565b60208082526019908201527f416363657373436f6e74726f6c3a2043454f5f44454e49454400000000000000604082015260600190565b6020808252601a908201527f546f6b656e4875623a204445504f5349545f434f4f4c444f574e000000000000604082015260600190565b634e487b7160e01b5f52603260045260245ffd5b5f60ff821660ff810361184a5761184a6116d0565b60010192915050565b81810381811115610e9757610e976116d0565b5f60208284031215611876575f80fd5b5051919050565b5f6020828403121561188d575f80fd5b815161153f8161158756fe7472616e7366657246726f6d28616464726573732c616464726573732c75696e74323536294d6574615472616e73616374696f6e2875696e74323536206e6f6e63652c616464726573732066726f6d2c62797465732066756e6374696f6e5369676e617475726529a2646970667358221220c5703897802bf6ac1308c073afe5f1f8c1a5eb11c535ebe17afb21ca6f999b0f64736f6c63430008150033

Verified Source Code Partial Match

Compiler: v0.8.21+commit.d9974bed EVM: shanghai Optimization: Yes (200 runs)
TokenHub.sol 216 lines
// SPDX-License-Identifier: -- DG --

pragma solidity =0.8.21;

import "./Interfaces.sol";
import "./TransferHelper.sol";
import "./AccessController.sol";
import "./EIP712MetaTransaction.sol";

contract TokenHub is
    AccessController,
    TransferHelper,
    EIP712MetaTransaction
{    
    uint256 public forwardFrame;
    address public forwardAddress;

    receive()
        external
        payable
    {
        emit ReceiveNative(
            msg.value
        );
    }

    mapping(address => bool) public supportedTokens;
    mapping(address => uint256) public forwardFrames;

    event Forward(
        address indexed depositorAddress,
        address indexed paymentTokenAddress,
        uint256 indexed paymentTokenAmount
    );

    event ForwardNative(
        address indexed depositorAddress,
        uint256 indexed paymentTokenAmount
    );

    event ReceiveNative(
        uint256 indexed nativeAmount
    );

    constructor(
        address _defaultToken,
        uint256 _defaultFrame,
        address _defaultAddress
    )
        EIP712Base(
            "TokenHub",
            "v3.0"
        )
    {
        forwardFrame = _defaultFrame;
        forwardAddress = _defaultAddress;        
        supportedTokens[_defaultToken] = true;
    }

    function forwardNative()
        external
        payable 
    {
        address _depositorAddress = msg.sender;

        require(
            canDepositAgain(_depositorAddress),
            "TokenHub: DEPOSIT_COOLDOWN"
        );

        forwardFrames[_depositorAddress] = block.number;

        payable(forwardAddress).transfer(
            msg.value
        );

        emit ForwardNative(
            msg.sender,
            msg.value
        );        
    }

    function forwardTokens(
        address _paymentToken,
        uint256 _paymentTokenAmount
    )
        external
    {
        address _depositorAddress = msg.sender;

        require(
            canDepositAgain(_depositorAddress),
            "TokenHub: DEPOSIT_COOLDOWN"
        );

        forwardFrames[_depositorAddress] = block.number;

        require(
            supportedTokens[_paymentToken],
            "TokenHub: UNSUPPORTED_TOKEN"
        );

        safeTransferFrom(
            _paymentToken,
            _depositorAddress,
            forwardAddress,
            _paymentTokenAmount
        );

        emit Forward(
            msg.sender,
            _paymentToken,
            _paymentTokenAmount
        );
    }

    function forwardTokensByWorker(
        address _depositorAddress,
        address _paymentTokenAddress,
        uint256 _paymentTokenAmount
    )
        external
        onlyWorker
    {
        require(
            canDepositAgain(_depositorAddress),
            "TokenHub: DEPOSIT_COOLDOWN"
        );

        forwardFrames[_depositorAddress] = block.number;

        require(
            supportedTokens[_paymentTokenAddress],
            "TokenHub: UNSUPPORTED_TOKEN"
        );

        safeTransferFrom(
            _paymentTokenAddress,
            _depositorAddress,
            forwardAddress,
            _paymentTokenAmount
        );

        emit Forward(
            _depositorAddress,
            _paymentTokenAddress,
            _paymentTokenAmount
        );
    }

    function changeForwardFrame(
        uint256 _newDepositFrame
    )
        external
        onlyCEO
    {
        forwardFrame = _newDepositFrame;
    }

    function changeForwardAddress(
        address _newForwardAddress
    )
        external
        onlyCEO
    {
        forwardAddress = _newForwardAddress;
    }

    function changeSupportedToken(
        address _tokenAddress,
        bool _supportStatus
    )
        external 
        onlyCEO
    {
        supportedTokens[_tokenAddress] = _supportStatus;
    }

    function canDepositAgain(
        address _depositorAddress
    )
        public
        view
        returns (bool)
    {
        return block.number - forwardFrames[_depositorAddress] >= forwardFrame;
    }

    function rescueToken(
        address _tokenAddress
    )
        external
        onlyCEO
    {
        uint256 tokenBalance = safeBalance(
            _tokenAddress,
            address(this)
        );

        safeTransfer(
            _tokenAddress,
            msg.sender,
            tokenBalance
        );
    }

    function rescueNative() 
        external 
        onlyCEO 
    {
        uint256 etherBalance = address(this).balance;
        require(etherBalance > 0, "No Ether balance to rescue");
        
        payable(msg.sender).transfer(etherBalance);
    }
}
EIP712Base.sol 68 lines
// SPDX-License-Identifier: -- DG --

pragma solidity =0.8.21;

contract EIP712Base {

    struct EIP712Domain {
        string name;
        string version;
        uint256 chainId;
        address verifyingContract;
    }

    bytes32 internal constant EIP712_DOMAIN_TYPEHASH = keccak256(
        bytes(
            "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
        )
    );

    bytes32 internal domainSeperator;

    constructor(
        string memory _name,
        string memory _version
    ) {
        domainSeperator = keccak256(abi.encode(
			EIP712_DOMAIN_TYPEHASH,
			keccak256(bytes(_name)),
			keccak256(bytes(_version)),
			getChainID(),
			address(this)
		));
    }

    function getChainID()
        internal
        pure
        returns (uint256 id)
    {
		assembly {
			id := 1
		}
	}

    function getDomainSeperator()
        private
        view
        returns(bytes32)
    {
		return domainSeperator;
	}

    function toTypedMessageHash(
        bytes32 _messageHash
    )
        internal
        view
        returns(bytes32)
    {
        return keccak256(
            abi.encodePacked(
                "\x19\x01",
                getDomainSeperator(),
                _messageHash
            )
        );
    }
}
Interfaces.sol 82 lines
// SPDX-License-Identifier: -- DG --

pragma solidity =0.8.21;

interface ERC721 {

    function ownerOf(
        uint256 _tokenId
    )
        external
        view
        returns (address);

    function transferFrom(
        address _from,
        address _to,
        uint256 _tokenId
    )
        external;
}

interface ERC20 {

    function approve(
        address spender,
        uint256 amount
    )
        external 
        returns (bool);
        
    function burn(
        uint256 _amount
    )
        external;
}

interface DGAccessories  {

    function issueTokens(
        address[] calldata _beneficiaries,
        uint256[] calldata _itemIds
    )
        external;

    function encodeTokenId(
        uint256 _itemId,
        uint256 _issuedId
    )
        external
        pure
        returns (uint256 id);

    function decodeTokenId(
        uint256 _tokenId
    )
        external
        pure
        returns (
            uint256 itemId,
            uint256 issuedId
        );

    function items(
        uint256 _id
    )
        external
        view
        returns (
            string memory rarity,
            uint256 maxSupply,
            uint256 totalSupply,
            uint256 price,
            address beneficiary,
            string memory metadata,
            string memory contentHash
        );

    function itemsCount()
        external
        view
        returns (uint256);
}
TransferHelper.sol 104 lines
// SPDX-License-Identifier: -- DG --

pragma solidity =0.8.21;

contract TransferHelper {

    bytes4 private constant TRANSFER = bytes4(
        keccak256(
            bytes(
                "transfer(address,uint256)" // 0xa9059cbb
            )
        )
    );

    bytes4 private constant TRANSFER_FROM = bytes4(
        keccak256(
            bytes(
                "transferFrom(address,address,uint256)" // 0x23b872dd
            )
        )
    );

    bytes4 private constant BALANCE_OF = bytes4(
        keccak256(
            bytes(
                "balanceOf(address)"
            )
        )
    );

    function safeTransfer(
        address _token,
        address _to,
        uint256 _value
    )
        internal
    {
        (bool success, bytes memory data) = _token.call(
            abi.encodeWithSelector(
                TRANSFER, // 0xa9059cbb
                _to,
                _value
            )
        );

        require(
            success && (
                data.length == 0 || abi.decode(
                    data, (bool)
                )
            ),
            "TransferHelper: TRANSFER_FAILED"
        );
    }

    function safeTransferFrom(
        address _token,
        address _from,
        address _to,
        uint _value
    )
        internal
    {
        (bool success, bytes memory data) = _token.call(
            abi.encodeWithSelector(
                TRANSFER_FROM,
                _from,
                _to,
                _value
            )
        );

        require(
            success && (
                data.length == 0 || abi.decode(
                    data, (bool)
                )
            ),
            "TransferHelper: TRANSFER_FROM_FAILED"
        );
    }

    function safeBalance(
        address _token,
        address _owner
    )
        internal
        returns (uint256)
    {
        (bool success, bytes memory data) = _token.call(
            abi.encodeWithSelector(
                BALANCE_OF,
                _owner
            )
        );

        if (success == false) return 0;

        return abi.decode(
            data,
            (uint256)
        );
    }
}
AccessController.sol 156 lines
// SPDX-License-Identifier: -- DG --

pragma solidity =0.8.21;

contract AccessController {

    address public ceoAddress;
    mapping (address => bool) public isWorker;

    event CEOSet(
        address newCEO
    );

    event WorkerAdded(
        address newWorker
    );

    event WorkerRemoved(
        address existingWorker
    );

    constructor() {

        address creator = msg.sender;
        ceoAddress = creator;
        isWorker[creator] = true;

        emit CEOSet(
            creator
        );

        emit WorkerAdded(
            creator
        );
    }

    modifier onlyCEO() {
        require(
            msg.sender == ceoAddress,
            "AccessControl: CEO_DENIED"
        );
        _;
    }

    modifier onlyWorker() {
        require(
            isWorker[msg.sender] == true,
            "AccessControl: WORKER_DENIED"
        );
        _;
    }

    modifier nonZeroAddress(
        address checkingAddress
    ) {
        require(
            checkingAddress != address(0x0),
            "AccessControl: INVALID_ADDRESS"
        );
        _;
    }

    function setCEO(
        address _newCEO
    )
        external
        nonZeroAddress(_newCEO)
        onlyCEO
    {
        ceoAddress = _newCEO;

        emit CEOSet(
            ceoAddress
        );
    }

    function addWorker(
        address _newWorker
    )
        external
        onlyCEO
    {
        _addWorker(
            _newWorker
        );
    }

    function addWorkerBulk(
        address[] calldata _newWorkers
    )
        external
        onlyCEO
    {
        for (uint8 index = 0; index < _newWorkers.length; index++) {
            _addWorker(_newWorkers[index]);
        }
    }

    function _addWorker(
        address _newWorker
    )
        internal
        nonZeroAddress(_newWorker)
    {
        require(
            isWorker[_newWorker] == false,
            'AccessControl: worker already exist'
        );

        isWorker[_newWorker] = true;

        emit WorkerAdded(
            _newWorker
        );
    }

    function removeWorker(
        address _existingWorker
    )
        external
        onlyCEO
    {
        _removeWorker(
            _existingWorker
        );
    }

    function removeWorkerBulk(
        address[] calldata _workerArray
    )
        external
        onlyCEO
    {
        for (uint8 index = 0; index < _workerArray.length; index++) {
            _removeWorker(_workerArray[index]);
        }
    }

    function _removeWorker(
        address _existingWorker
    )
        internal
        nonZeroAddress(_existingWorker)
    {
        require(
            isWorker[_existingWorker] == true,
            "AccessControl: worker not detected"
        );

        isWorker[_existingWorker] = false;

        emit WorkerRemoved(
            _existingWorker
        );
    }
}
EIP712MetaTransaction.sol 157 lines
// SPDX-License-Identifier: -- DG --

pragma solidity =0.8.21;

import "./EIP712Base.sol";

abstract contract EIP712MetaTransaction is EIP712Base {

    bytes32 private constant META_TRANSACTION_TYPEHASH = keccak256(
        bytes(
            "MetaTransaction(uint256 nonce,address from,bytes functionSignature)"
        )
    );

    event MetaTransactionExecuted(
        address userAddress,
        address payable relayerAddress,
        bytes functionSignature
    );

    mapping(address => uint256) internal nonces;

    struct MetaTransaction {
		uint256 nonce;
		address from;
        bytes functionSignature;
	}

    function executeMetaTransaction(
        address _userAddress,
        bytes memory _functionSignature,
        bytes32 _sigR,
        bytes32 _sigS,
        uint8 _sigV
    )
        public
        payable
        returns(bytes memory)
    {
        MetaTransaction memory metaTx = MetaTransaction(
            {
                nonce: nonces[_userAddress],
                from: _userAddress,
                functionSignature: _functionSignature
            }
        );

        require(
            verify(
                _userAddress,
                metaTx,
                _sigR,
                _sigS,
                _sigV
            ), "EIP712MetaTransaction: INVALID_SIGNATURE"
        );

	    nonces[_userAddress] =
	    nonces[_userAddress] + 1;

        (bool success, bytes memory returnData) = address(this).call(
            abi.encodePacked(
                _functionSignature,
                _userAddress
            )
        );

        require(
            success,
            "EIP712MetaTransaction: INVALID_CALL"
        );

        emit MetaTransactionExecuted(
            _userAddress,
            payable(msg.sender),
            _functionSignature
        );

        return returnData;
    }

    function hashMetaTransaction(
        MetaTransaction memory _metaTx
    )
        internal
        pure
        returns (bytes32)
    {
		return keccak256(
		    abi.encode(
                META_TRANSACTION_TYPEHASH,
                _metaTx.nonce,
                _metaTx.from,
                keccak256(_metaTx.functionSignature)
            )
        );
	}

    function verify(
        address _user,
        MetaTransaction memory _metaTx,
        bytes32 _sigR,
        bytes32 _sigS,
        uint8 _sigV
    )
        internal
        view
        returns (bool)
    {
        address signer = ecrecover(
            toTypedMessageHash(
                hashMetaTransaction(_metaTx)
            ),
            _sigV,
            _sigR,
            _sigS
        );

        require(
            signer != address(0x0),
            "EIP712MetaTransaction: INVALID_SIGNATURE"
        );

		return signer == _user;
	}

    function msgSender()
        internal
        view
        returns(address sender)
    {
        if (msg.sender == address(this)) {

            bytes memory array = msg.data;
            uint256 index = msg.data.length;

            assembly {
                // Load the 32 bytes word from memory with the address on the lower 20 bytes, and mask those.
                sender := and(mload(add(array, index)), 0xffffffffffffffffffffffffffffffffffffffff)
            }
        } else {
            sender = msg.sender;
        }

        return sender;
    }

    function getNonce(
        address _user
    )
        external
        view
        returns(uint256 nonce)
    {
        nonce = nonces[_user];
    }
}

Read Contract

canDepositAgain 0xd239c973 → bool
ceoAddress 0x0a0f8168 → address
forwardAddress 0x21507b4e → address
forwardFrame 0x799bf3f9 → uint256
forwardFrames 0xc5b3ffe9 → uint256
getNonce 0x2d0335ab → uint256
isWorker 0xaa156645 → bool
supportedTokens 0x68c4ac26 → bool

Write Contract 14 functions

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

addWorker 0x806ad57e
address _newWorker
addWorkerBulk 0xc3170007
address[] _newWorkers
changeForwardAddress 0x5af2e9fb
address _newForwardAddress
changeForwardFrame 0x983c45cf
uint256 _newDepositFrame
changeSupportedToken 0x5eae21fa
address _tokenAddress
bool _supportStatus
executeMetaTransaction 0x0c53c51c
address _userAddress
bytes _functionSignature
bytes32 _sigR
bytes32 _sigS
uint8 _sigV
returns: bytes
forwardNative 0xefd00e8a
No parameters
forwardTokens 0x45e0e412
address _paymentToken
uint256 _paymentTokenAmount
forwardTokensByWorker 0x877f210c
address _depositorAddress
address _paymentTokenAddress
uint256 _paymentTokenAmount
removeWorker 0xc4f987a5
address _existingWorker
removeWorkerBulk 0xe6adfe37
address[] _workerArray
rescueNative 0xfc82f084
No parameters
rescueToken 0x4460d3cf
address _tokenAddress
setCEO 0x27d7874c
address _newCEO

Recent Transactions

No transactions found for this address