Forkchoice Ethereum Mainnet

Address Contract Partially Verified

Address 0x237EDCDd43349227ef511581Cc834962ECf23076
Balance 0 ETH
Nonce 1
Code Size 15393 bytes
Indexed Transactions 0 (1 on-chain, 0.9% indexed)
External Etherscan · Sourcify

Contract Bytecode

15393 bytes
0x60806040526004361061011f5760003560e01c80635b4e128c116100a0578063bc197c8111610064578063bc197c8114610408578063d5553b8814610445578063d59e3e9814610482578063ec5e319e146104bf578063f23a6e61146104ea5761011f565b80635b4e128c14610323578063792c891f1461034c5780637e7fd66c146103895780639565389e146103b4578063affed0e0146103dd5761011f565b806326aa4655116100e757806326aa4655146102185780633408e4701461025557806340914b06146102805780634f1ef286146102bd5780635175ca5e146102e65761011f565b806313f8c57814610121578063150b7a021461014a5780631b9a9f9e146101875780631f602092146101b057806320c13b0b146101db575b005b34801561012d57600080fd5b506101486004803603610143919081019061239d565b610527565b005b34801561015657600080fd5b50610171600480360361016c919081019061250d565b6106e6565b60405161017e9190613588565b60405180910390f35b34801561019357600080fd5b506101ae60048036036101a9919081019061239d565b6106fa565b005b3480156101bc57600080fd5b506101c56107f4565b6040516101d291906135a3565b60405180910390f35b3480156101e757600080fd5b5061020260048036036101fd91908101906128e4565b61082d565b60405161020f9190613588565b60405180910390f35b34801561022457600080fd5b5061023f600480360361023a91908101906126f0565b6108a5565b60405161024c9190613506565b60405180910390f35b34801561026157600080fd5b5061026a610964565b6040516102779190613867565b60405180910390f35b34801561028c57600080fd5b506102a760048036036102a291908101906128e4565b61096d565b6040516102b49190613588565b60405180910390f35b3480156102c957600080fd5b506102e460048036036102df919081019061261a565b610a04565b005b3480156102f257600080fd5b5061030d6004803603610308919081019061239d565b610b84565b60405161031a9190613528565b60405180910390f35b34801561032f57600080fd5b5061034a60048036036103459190810190612991565b610ba4565b005b34801561035857600080fd5b50610373600480360361036e91908101906126af565b610c58565b6040516103809190613506565b60405180910390f35b34801561039557600080fd5b5061039e610ce8565b6040516103ab9190613867565b60405180910390f35b3480156103c057600080fd5b506103db60048036036103d6919081019061239d565b610cee565b005b3480156103e957600080fd5b506103f2610ef3565b6040516103ff9190613867565b60405180910390f35b34801561041457600080fd5b5061042f600480360361042a9190810190612441565b610ef9565b60405161043c9190613588565b60405180910390f35b34801561045157600080fd5b5061046c600480360361046791908101906127a9565b610f11565b6040516104799190613506565b60405180910390f35b34801561048e57600080fd5b506104a960048036036104a491908101906128e4565b610fcf565b6040516104b69190613588565b60405180910390f35b3480156104cb57600080fd5b506104d4611121565b6040516104e19190613867565b60405180910390f35b3480156104f657600080fd5b50610511600480360361050c9190810190612588565b611127565b60405161051e9190613588565b60405180910390f35b6105303361113d565b8061056657503073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6105a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161059c906137c7565b60405180910390fd5b60001515600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514610638576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161062f906137e7565b60405180910390fd5b60018060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555060016003600082825401925050819055508073ffffffffffffffffffffffffffffffffffffffff167fb020719d16d3c4de45a91f9c329aa61d5bad3f44f760840c8d5d82d4cd3bcc3360405160405180910390a250565b600063150b7a0260e01b9050949350505050565b600080541461073e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161073590613727565b60405180910390fd5b600160008190555060018060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555060016003600082825401925050819055508073ffffffffffffffffffffffffffffffffffffffff167fb020719d16d3c4de45a91f9c329aa61d5bad3f44f760840c8d5d82d4cd3bcc3360405160405180910390a250565b6040518060400160405280600a81526020017f323032303036303130300000000000000000000000000000000000000000000081525081565b600060418251141561084a57610843838361096d565b905061089f565b60828251106108645761085d8383610fcf565b905061089f565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161089690613747565b60405180910390fd5b92915050565b606060005a9050600061091a306000357fffffffff00000000000000000000000000000000000000000000000000000000166108df610964565b6002548d8d8d8d8d6040516020016108ff99989796959493929190613419565b60405160208183030381529060405280519060200120611193565b905061092681856111c3565b60606109358a8a8a8a8a611227565b9150506109418a611456565b1561095457610953838a8a8a8a6114e5565b5b8093505050509695505050505050565b60006001905090565b600060418251146109b3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109aa90613687565b60405180910390fd5b60006109d0836109c28661179a565b6117d590919063ffffffff16565b905060006109dd8261113d565b6109ee5763ffffffff60e01b6109f7565b6320c13b0b60e01b5b9050809250505092915050565b3073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610a72576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a6990613647565b60405180910390fd5b610a7b826118c1565b600060608373ffffffffffffffffffffffffffffffffffffffff1683604051610aa4919061337d565b600060405180830381855af49150503d8060008114610adf576040519150601f19603f3d011682016040523d82523d6000602084013e610ae4565b606091505b50915091506060610af482611938565b9050828190610b39576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b3091906135c5565b60405180910390fd5b508473ffffffffffffffffffffffffffffffffffffffff167fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b60405160405180910390a25050505050565b60016020528060005260406000206000915054906101000a900460ff1681565b600160005414610be9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610be090613787565b60405180910390fd5b600260008190555060008114610c55576000478210610c085747610c0a565b815b90503273ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015610c52573d6000803e3d6000fd5b50505b50565b6060610c633361113d565b80610c9957503073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b610cd8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ccf906137c7565b60405180910390fd5b610ce18261199e565b9050919050565b60005481565b610cf73361113d565b80610d2d57503073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b610d6c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d63906137c7565b60405180910390fd5b60011515600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16151514610dff576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610df690613807565b60405180910390fd5b600160035411610e44576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610e3b906136e7565b60405180910390fd5b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555060016003600082825403925050819055508073ffffffffffffffffffffffffffffffffffffffff167fbe55f9add9abe657e689a4a84a31854310f260c7e2610bcd22440e3ec3a836a460405160405180910390a250565b60025481565b600063bc197c8160e01b905098975050505050505050565b606060005a9050610f228a88611a32565b6000610f90306000357fffffffff0000000000000000000000000000000000000000000000000000000016610f55610964565b6002548f8f8f8e8e604051602001610f7599989796959493929190613419565b60405160208183030381529060405280519060200120611193565b9050610f9e81868a87611b46565b6060610fad8c8c8c8b8b611227565b915050610fbd838c8c8b8b6114e5565b80935050505098975050505050505050565b6000608282511015611016576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161100d90613847565b60405180910390fd5b606061102f6000604185611bfa9092919063ffffffff16565b9050606061104960418086611bfa9092919063ffffffff16565b9050600061106260828651611c8690919063ffffffff16565b9050606061107c60828388611bfa9092919063ffffffff16565b9050600061109b8561108d8a61179a565b6117d590919063ffffffff16565b905060006110d082846040516020016110b59291906134d6565b60405160208183030381529060405280519060200120611193565b905060006110e786836117d590919063ffffffff16565b905060006110f48261113d565b6111055763ffffffff60e01b61110e565b6320c13b0b60e01b5b9050809850505050505050505092915050565b60035481565b600063f23a6e6160e01b90509695505050505050565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169050919050565b6000816040516020016111a69190613394565b604051602081830303815290604052805190602001209050919050565b60006111d882846117d590919063ffffffff16565b90506111e38161113d565b611222576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611219906136c7565b60405180910390fd5b505050565b600060603a86111561126e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611265906135e7565b60405180910390fd5b60006112dc306000357fffffffff00000000000000000000000000000000000000000000000000000000166112a1610964565b6002548c8c8c8c8c6040516020016112c199989796959493929190613419565b60405160208183030381529060405280519060200120611193565b90508751600260008282540192505081905550606063792c891f60e01b8960405160240161130a9190613506565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050600060603073ffffffffffffffffffffffffffffffffffffffff1683604051611392919061337d565b6000604051808303816000865af19150503d80600081146113cf576040519150601f19603f3d011682016040523d82523d6000602084013e6113d4565b606091505b509150915060608261142a5760606113eb83611938565b90507fb5e1dc2ddc0e1a0221e00b3c0446f36b707001d3ac7cfb494259863fdef7ccd78160405161141c91906135c5565b60405180910390a150611441565b8180602001905161143e919081019061266e565b90505b84819650965050505050509550959350505050565b60008060008090505b83518110156114d95761148484828151811061147757fe5b6020026020010151611cd0565b909150905050809250503073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16146114cc576001925050506114e0565b808060010191505061145f565b5060009150505b919050565b600061150c846114fe5a89611c8690919063ffffffff16565b611d0090919063ffffffff16565b9050600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141561161857476115578683611d5590919063ffffffff16565b1115611598576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161158f90613627565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff166115c28683611d5590919063ffffffff16565b6040516115ce906133e9565b60006040518083038185875af1925050503d806000811461160b576040519150601f19603f3d011682016040523d82523d6000602084013e611610565b606091505b505050611792565b600083905060006116328484611d5590919063ffffffff16565b90508173ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161166d91906133fe565b602060405180830381600087803b15801561168757600080fd5b505af115801561169b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506116bf91908101906129ba565b811115611701576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116f890613827565b60405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33836040518363ffffffff1660e01b815260040161173c9291906134ad565b602060405180830381600087803b15801561175657600080fd5b505af115801561176a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525061178e91908101906128bb565b5050505b505050505050565b60006117a68251611dc5565b826040516020016117b89291906133ba565b604051602081830303815290604052805190602001209050919050565b600060418251146117e957600090506118bb565b60008060006020850151925060408501519150606085015160001a90507f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08260001c111561183d57600093505050506118bb565b601b8160ff16141580156118555750601c8160ff1614155b1561186657600093505050506118bb565b600186828585604051600081526020016040526040516118899493929190613543565b6020604051602081039080840390855afa1580156118ab573d6000803e3d6000fd5b5050506020604051035193505050505b92915050565b6118ca81611ef8565b611909576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161190090613707565b60405180910390fd5b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b90508181555050565b606060448251101561196457604051806060016040528060218152602001613bbe602191399050611999565b606061197f60048085510385611bfa9092919063ffffffff16565b9050808060200190516119959190810190612950565b9150505b919050565b60608082516040519080825280602002602001820160405280156119d657816020015b60608152602001906001900390816119c15790505b50905060008090505b8351811015611a2857611a048482815181106119f757fe5b6020026020010151611f0b565b828281518110611a1057fe5b602002602001018190525080806001019150506119df565b5080915050919050565b600080600090505b8351811015611ae557611a5f848281518110611a5257fe5b6020026020010151611cd0565b909150905050809250503073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611ad8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611acf90613767565b60405180910390fd5b8080600101915050611a3a565b50600082806020019051611afc91908101906129ba565b9050428111611b40576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b37906136a7565b60405180910390fd5b50505050565b6000611b5b84866117d590919063ffffffff16565b90506000611b908285604051602001611b759291906134d6565b60405160208183030381529060405280519060200120611193565b90506000611ba784836117d590919063ffffffff16565b9050611bb28161113d565b611bf1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611be890613607565b60405180910390fd5b50505050505050565b606081830184511015611c0c57600080fd5b6060821560008114611c2957604051915060208201604052611c7a565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015611c675780518352602083019250602081019050611c4a565b50868552601f19601f8301166040525050505b50809150509392505050565b6000611cc883836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250611f3c565b905092915050565b6000806000606084806020019051611ceb91908101906123c6565b83935080905093509350935093509193509193565b600080828401905083811015611d4b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d4290613667565b60405180910390fd5b8091505092915050565b600080831415611d685760009050611dbf565b6000828402905082848281611d7957fe5b0414611dba576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611db1906137a7565b60405180910390fd5b809150505b92915050565b60606000821415611e0d576040518060400160405280600181526020017f30000000000000000000000000000000000000000000000000000000000000008152509050611ef3565b6000829050600083905060005b60008214611e3c578080600101915050600a8281611e3457fe5b049150611e1a565b6060816040519080825280601f01601f191660200182016040528015611e715781602001600182028038833980820191505090505b50905060006001830390505b60008514611eea57600a8581611e8f57fe5b0660300160f81b82828060019003935081518110611ea957fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a8581611ee257fe5b049450611e7d565b81955050505050505b919050565b600080823b905060008111915050919050565b606060008060006060611f1d86611cd0565b9350935093509350611f3184848484611f97565b945050505050919050565b6000838311158290611f84576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611f7b91906135c5565b60405180910390fd5b5060008385039050809150509392505050565b6060600060608673ffffffffffffffffffffffffffffffffffffffff16858786604051611fc4919061337d565b600060405180830381858888f193505050503d8060008114612002576040519150601f19603f3d011682016040523d82523d6000602084013e612007565b606091505b50915091508161205b57606061201c82611938565b9050806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161205291906135c5565b60405180910390fd5b8092505050949350505050565b60008135905061207781613b61565b92915050565b60008151905061208c81613b78565b92915050565b600082601f8301126120a357600080fd5b81516120b66120b1826138af565b613882565b9150818183526020840193506020810190508360005b838110156120fc57815186016120e28882612277565b8452602084019350602083019250506001810190506120cc565b5050505092915050565b600082601f83011261211757600080fd5b813561212a612125826138d7565b613882565b9150818183526020840193506020810190508360005b8381101561217057813586016121568882612223565b845260208401935060208301925050600181019050612140565b5050505092915050565b60008083601f84011261218c57600080fd5b8235905067ffffffffffffffff8111156121a557600080fd5b6020830191508360208202830111156121bd57600080fd5b9250929050565b6000815190506121d381613b8f565b92915050565b60008083601f8401126121eb57600080fd5b8235905067ffffffffffffffff81111561220457600080fd5b60208301915083600182028301111561221c57600080fd5b9250929050565b600082601f83011261223457600080fd5b8135612247612242826138ff565b613882565b9150808252602083016020830185838301111561226357600080fd5b61226e838284613b04565b50505092915050565b600082601f83011261228857600080fd5b815161229b612296826138ff565b613882565b915080825260208301602083018583830111156122b757600080fd5b6122c2838284613b13565b50505092915050565b600082601f8301126122dc57600080fd5b81356122ef6122ea8261392b565b613882565b9150808252602083016020830185838301111561230b57600080fd5b612316838284613b04565b50505092915050565b600082601f83011261233057600080fd5b815161234361233e82613957565b613882565b9150808252602083016020830185838301111561235f57600080fd5b61236a838284613b13565b50505092915050565b60008135905061238281613ba6565b92915050565b60008151905061239781613ba6565b92915050565b6000602082840312156123af57600080fd5b60006123bd84828501612068565b91505092915050565b600080600080608085870312156123dc57600080fd5b60006123ea8782880161207d565b94505060206123fb87828801612388565b935050604061240c87828801612388565b925050606085015167ffffffffffffffff81111561242957600080fd5b61243587828801612277565b91505092959194509250565b60008060008060008060008060a0898b03121561245d57600080fd5b600061246b8b828c01612068565b985050602061247c8b828c01612068565b975050604089013567ffffffffffffffff81111561249957600080fd5b6124a58b828c0161217a565b9650965050606089013567ffffffffffffffff8111156124c457600080fd5b6124d08b828c0161217a565b9450945050608089013567ffffffffffffffff8111156124ef57600080fd5b6124fb8b828c016121d9565b92509250509295985092959890939650565b6000806000806080858703121561252357600080fd5b600061253187828801612068565b945050602061254287828801612068565b935050604061255387828801612373565b925050606085013567ffffffffffffffff81111561257057600080fd5b61257c878288016122cb565b91505092959194509250565b60008060008060008060a087890312156125a157600080fd5b60006125af89828a01612068565b96505060206125c089828a01612068565b95505060406125d189828a01612373565b94505060606125e289828a01612373565b935050608087013567ffffffffffffffff8111156125ff57600080fd5b61260b89828a016121d9565b92509250509295509295509295565b6000806040838503121561262d57600080fd5b600061263b85828601612068565b925050602083013567ffffffffffffffff81111561265857600080fd5b612664858286016122cb565b9150509250929050565b60006020828403121561268057600080fd5b600082015167ffffffffffffffff81111561269a57600080fd5b6126a684828501612092565b91505092915050565b6000602082840312156126c157600080fd5b600082013567ffffffffffffffff8111156126db57600080fd5b6126e784828501612106565b91505092915050565b60008060008060008060c0878903121561270957600080fd5b600087013567ffffffffffffffff81111561272357600080fd5b61272f89828a01612106565b965050602061274089828a01612373565b955050604061275189828a01612373565b945050606061276289828a01612068565b935050608061277389828a01612373565b92505060a087013567ffffffffffffffff81111561279057600080fd5b61279c89828a016122cb565b9150509295509295509295565b600080600080600080600080610100898b0312156127c657600080fd5b600089013567ffffffffffffffff8111156127e057600080fd5b6127ec8b828c01612106565b98505060206127fd8b828c01612373565b975050604061280e8b828c01612373565b965050606089013567ffffffffffffffff81111561282b57600080fd5b6128378b828c016122cb565b95505060806128488b828c01612068565b94505060a06128598b828c01612373565b93505060c089013567ffffffffffffffff81111561287657600080fd5b6128828b828c016122cb565b92505060e089013567ffffffffffffffff81111561289f57600080fd5b6128ab8b828c016122cb565b9150509295985092959890939650565b6000602082840312156128cd57600080fd5b60006128db848285016121c4565b91505092915050565b600080604083850312156128f757600080fd5b600083013567ffffffffffffffff81111561291157600080fd5b61291d858286016122cb565b925050602083013567ffffffffffffffff81111561293a57600080fd5b612946858286016122cb565b9150509250929050565b60006020828403121561296257600080fd5b600082015167ffffffffffffffff81111561297c57600080fd5b6129888482850161231f565b91505092915050565b6000602082840312156129a357600080fd5b60006129b184828501612373565b91505092915050565b6000602082840312156129cc57600080fd5b60006129da84828501612388565b91505092915050565b60006129ef8383612b47565b905092915050565b612a0081613ace565b82525050565b612a0f81613a43565b82525050565b612a1e81613a31565b82525050565b6000612a2f82613993565b612a3981856139d7565b935083602082028501612a4b85613983565b8060005b85811015612a875784840389528151612a6885826129e3565b9450612a73836139ca565b925060208a01995050600181019050612a4f565b50829750879550505050505092915050565b612aa281613a55565b82525050565b612ab181613a61565b82525050565b612ac8612ac382613a61565b613b46565b82525050565b612ad781613a6b565b82525050565b6000612ae8826139a9565b612af281856139f9565b9350612b02818560208601613b13565b612b0b81613b50565b840191505092915050565b6000612b21826139a9565b612b2b8185613a0a565b9350612b3b818560208601613b13565b80840191505092915050565b6000612b528261399e565b612b5c81856139e8565b9350612b6c818560208601613b13565b612b7581613b50565b840191505092915050565b6000612b8b826139bf565b612b958185613a15565b9350612ba5818560208601613b13565b612bae81613b50565b840191505092915050565b6000612bc4826139bf565b612bce8185613a26565b9350612bde818560208601613b13565b80840191505092915050565b6000612bf5826139b4565b612bff8185613a15565b9350612c0f818560208601613b13565b612c1881613b50565b840191505092915050565b6000612c30602483613a15565b91507f424d54413a204e6f742061206c6172676520656e6f7567682074782e6761737060008301527f72696365000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612c96601a83613a15565b91507f4c4b4d54413a2041757468206b657920697320696e76616c69640000000000006000830152602082019050919050565b6000612cd6601c83613a26565b91507f19457468657265756d205369676e6564204d6573736167653a0a3332000000006000830152601c82019050919050565b6000612d16602583613a15565b91507f42413a20496e73756666696369656e742067617320284554482920666f72207260008301527f6566756e640000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612d7c601583613a15565b91507f42413a204f6e6c792073656c6620616c6c6f77656400000000000000000000006000830152602082019050919050565b6000612dbc601b83613a15565b91507f536166654d6174683a206164646974696f6e206f766572666c6f7700000000006000830152602082019050919050565b6000612dfc603a83613a15565b91507f455243313237313a20496e76616c696420697356616c6964417574684b65795360008301527f69676e6174757265205f7369676e6174757265206c656e6774680000000000006020830152604082019050919050565b6000612e62601b83613a15565b91507f4c4b4d54413a204c6f67696e206b6579206973206578706972656400000000006000830152602082019050919050565b6000612ea2601a83613a15565b91507f414b4d54413a2041757468206b657920697320696e76616c69640000000000006000830152602082019050919050565b6000612ee2601f83613a15565b91507f42413a2043616e6e6f742072656d6f7665206c6173742061757468206b6579006000830152602082019050919050565b6000612f22603f83613a15565b91507f41553a2043616e6e6f742073657420612070726f787920696d706c656d656e7460008301527f6174696f6e20746f2061206e6f6e2d636f6e74726163742061646472657373006020830152604082019050919050565b6000612f88602183613a15565b91507f41493a20496d70726f70657220696e697469616c697a6174696f6e206f72646560008301527f72000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000612fee603383613a15565b91507f455243313237313a20496e76616c696420697356616c69645369676e6174757260008301527f65205f7369676e6174757265206c656e677468000000000000000000000000006020830152604082019050919050565b6000613054602983613a15565b91507f4c4b4d54413a204c6f67696e206b6579206973206e6f742061626c6520746f2060008301527f63616c6c2073656c6600000000000000000000000000000000000000000000006020830152604082019050919050565b60006130ba602283613a15565b91507f4149323a20496d70726f70657220696e697469616c697a6174696f6e206f726460008301527f65720000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613120602183613a15565b91507f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60008301527f77000000000000000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613186601a83613a26565b91507f19457468657265756d205369676e6564204d6573736167653a0a0000000000006000830152601a82019050919050565b60006131c6601f83613a15565b91507f42413a2041757468206b6579206f722073656c6620697320696e76616c6964006000830152602082019050919050565b6000613206600083613a0a565b9150600082019050919050565b6000613220601a83613a15565b91507f42413a2041757468206b657920616c72656164792061646465640000000000006000830152602082019050919050565b6000613260601a83613a15565b91507f42413a2041757468206b6579206e6f74207965742061646465640000000000006000830152602082019050919050565b60006132a0602783613a15565b91507f42413a20496e73756666696369656e74206761732028746f6b656e2920666f7260008301527f20726566756e64000000000000000000000000000000000000000000000000006020830152604082019050919050565b6000613306603b83613a15565b91507f455243313237313a20496e76616c696420697356616c69644c6f67696e4b657960008301527f5369676e6174757265205f7369676e6174757265206c656e67746800000000006020830152604082019050919050565b61336881613ab7565b82525050565b61337781613ac1565b82525050565b60006133898284612b16565b915081905092915050565b600061339f82612cc9565b91506133ab8284612ab7565b60208201915081905092915050565b60006133c582613179565b91506133d18285612bb9565b91506133dd8284612b16565b91508190509392505050565b60006133f4826131f9565b9150819050919050565b600060208201905061341360008301846129f7565b92915050565b60006101208201905061342f600083018c612a06565b61343c602083018b612ace565b613449604083018a61335f565b613456606083018961335f565b81810360808301526134688188612a24565b905061347760a083018761335f565b61348460c083018661335f565b61349160e0830185612a15565b61349f61010083018461335f565b9a9950505050505050505050565b60006040820190506134c260008301856129f7565b6134cf602083018461335f565b9392505050565b60006040820190506134eb6000830185612a15565b81810360208301526134fd8184612add565b90509392505050565b600060208201905081810360008301526135208184612a24565b905092915050565b600060208201905061353d6000830184612a99565b92915050565b60006080820190506135586000830187612aa8565b613565602083018661336e565b6135726040830185612aa8565b61357f6060830184612aa8565b95945050505050565b600060208201905061359d6000830184612ace565b92915050565b600060208201905081810360008301526135bd8184612bea565b905092915050565b600060208201905081810360008301526135df8184612b80565b905092915050565b6000602082019050818103600083015261360081612c23565b9050919050565b6000602082019050818103600083015261362081612c89565b9050919050565b6000602082019050818103600083015261364081612d09565b9050919050565b6000602082019050818103600083015261366081612d6f565b9050919050565b6000602082019050818103600083015261368081612daf565b9050919050565b600060208201905081810360008301526136a081612def565b9050919050565b600060208201905081810360008301526136c081612e55565b9050919050565b600060208201905081810360008301526136e081612e95565b9050919050565b6000602082019050818103600083015261370081612ed5565b9050919050565b6000602082019050818103600083015261372081612f15565b9050919050565b6000602082019050818103600083015261374081612f7b565b9050919050565b6000602082019050818103600083015261376081612fe1565b9050919050565b6000602082019050818103600083015261378081613047565b9050919050565b600060208201905081810360008301526137a0816130ad565b9050919050565b600060208201905081810360008301526137c081613113565b9050919050565b600060208201905081810360008301526137e0816131b9565b9050919050565b6000602082019050818103600083015261380081613213565b9050919050565b6000602082019050818103600083015261382081613253565b9050919050565b6000602082019050818103600083015261384081613293565b9050919050565b60006020820190508181036000830152613860816132f9565b9050919050565b600060208201905061387c600083018461335f565b92915050565b6000604051905081810181811067ffffffffffffffff821117156138a557600080fd5b8060405250919050565b600067ffffffffffffffff8211156138c657600080fd5b602082029050602081019050919050565b600067ffffffffffffffff8211156138ee57600080fd5b602082029050602081019050919050565b600067ffffffffffffffff82111561391657600080fd5b601f19601f8301169050602081019050919050565b600067ffffffffffffffff82111561394257600080fd5b601f19601f8301169050602081019050919050565b600067ffffffffffffffff82111561396e57600080fd5b601f19601f8301169050602081019050919050565b6000819050602082019050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b6000613a3c82613a97565b9050919050565b6000613a4e82613a97565b9050919050565b60008115159050919050565b6000819050919050565b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b600060ff82169050919050565b6000613ad982613ae0565b9050919050565b6000613aeb82613af2565b9050919050565b6000613afd82613a97565b9050919050565b82818337600083830152505050565b60005b83811015613b31578082015181840152602081019050613b16565b83811115613b40576000848401525b50505050565b6000819050919050565b6000601f19601f8301169050919050565b613b6a81613a31565b8114613b7557600080fd5b50565b613b8181613a43565b8114613b8c57600080fd5b50565b613b9881613a55565b8114613ba357600080fd5b50565b613baf81613ab7565b8114613bba57600080fd5b5056fe42413a205472616e73616374696f6e2072657665727465642073696c656e746c79a365627a7a72315820ec5912b63ee7e8ce3188c8103cd3a9d58209d5c97fcfbbaf4c531aba98b319696c6578706572696d656e74616cf564736f6c63430005100040

Verified Source Code Partial Match

Compiler: v0.5.16+commit.9c3226ce EVM: istanbul Optimization: No
AuthereumAccount.sol 1750 lines
/**
 *Submitted for verification at Etherscan.io on 2020-08-13
*/

/**
Author: Authereum Labs, Inc.
*/

pragma solidity 0.5.16;
pragma experimental ABIEncoderV2;


/**
 * @title AccountStateV1
 * @author Authereum Labs, Inc.
 * @dev This contract holds the state variables used by the account contracts.
 * @dev This abstraction exists in order to retain the order of the state variables.
 */
contract AccountStateV1 {
    uint256 public lastInitializedVersion;
    mapping(address => bool) public authKeys;
    uint256 public nonce;
    uint256 public numAuthKeys;
}

/**
 * @title AccountState
 * @author Authereum Labs, Inc.
 * @dev This contract holds the state variables used by the account contracts.
 * @dev This exists as the main contract to hold state. This contract is inherited
 * @dev by Account.sol, which will not care about state as long as it inherits
 * @dev AccountState.sol. Any state variable additions will be made to the various
 * @dev versions of AccountStateVX that this contract will inherit.
 */
contract AccountState is AccountStateV1 {}

/**
 * @title AccountEvents
 * @author Authereum Labs, Inc.
 * @dev This contract holds the events used by the Authereum contracts.
 * @dev This abstraction exists in order to retain the order to give initialization functions
 * @dev access to events.
 * @dev This contract can be overwritten with no changes to the upgradeability.
 */
contract AccountEvents {

    /**
     * BaseAccount.sol
     */

    event AuthKeyAdded(address indexed authKey);
    event AuthKeyRemoved(address indexed authKey);
    event CallFailed(string reason);

    /**
     * AccountUpgradeability.sol
     */

    event Upgraded(address indexed implementation);
}

/**
 * @title AccountInitializeV1
 * @author Authereum Labs, Inc.
 * @dev This contract holds the initialize function used by the account contracts.
 * @dev This abstraction exists in order to retain the order of the initialization functions.
 */
contract AccountInitializeV1 is AccountState, AccountEvents {

    /// @dev Initialize the Authereum Account
    /// @param _authKey authKey that will own this account
    function initializeV1(
        address _authKey
    )
        public
    {
        require(lastInitializedVersion == 0, "AI: Improper initialization order");
        lastInitializedVersion = 1;

        // Add first authKey
        authKeys[_authKey] = true;
        numAuthKeys += 1;
        emit AuthKeyAdded(_authKey);
    }
}

/**
 * @title AccountInitializeV2
 * @author Authereum Labs, Inc.
 * @dev This contract holds the initialize function used by the account contracts.
 * @dev This abstraction exists in order to retain the order of the initialization functions.
 */
contract AccountInitializeV2 is AccountState {

    /// @dev Add the ability to refund the contract for a deployment
    /// @param _deploymentCost Cost of the deployment
    function initializeV2(
        uint256 _deploymentCost
    )
        public
    {
        require(lastInitializedVersion == 1, "AI2: Improper initialization order");
        lastInitializedVersion = 2;

        if (_deploymentCost != 0) {
            uint256 amountToTransfer = _deploymentCost < address(this).balance ? _deploymentCost : address(this).balance;
            tx.origin.transfer(amountToTransfer);
        }
    }
}

/**
 * @title AccountInitialize
 * @author Authereum Labs, Inc.
 * @dev This contract holds the intialize functions used by the account contracts.
 * @dev This exists as the main contract to hold these functions. This contract is inherited
 * @dev by AuthereumAccount.sol, which will not care about initialization functions as long as it inherits
 * @dev AccountInitialize.sol. Any initialization function additions will be made to the various
 * @dev versions of AccountInitializeVx that this contract will inherit.
 */
contract AccountInitialize is AccountInitializeV1, AccountInitializeV2 {}

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 *
 * This contract is from openzeppelin-solidity 2.4.0
 */
contract IERC721Receiver {
    /**
     * @notice Handle the receipt of an NFT
     * @dev The ERC721 smart contract calls this function on the recipient
     * after a {IERC721-safeTransferFrom}. This function MUST return the function selector,
     * otherwise the caller will revert the transaction. The selector to be
     * returned can be obtained as `this.onERC721Received.selector`. This
     * function MAY throw to revert and reject the transfer.
     * Note: the ERC721 contract address is always the message sender.
     * @param operator The address which called `safeTransferFrom` function
     * @param from The address which previously owned the token
     * @param tokenId The NFT identifier which is being transferred
     * @param data Additional data with no specified format
     * @return bytes4 `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
     */
    function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data) public returns (bytes4);
}

/**
    Note: The ERC-165 identifier for this interface is 0x4e2312e0.
*/
interface IERC1155TokenReceiver {
    /**
        @notice Handle the receipt of a single ERC1155 token type.
        @dev An ERC1155-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeTransferFrom` after the balance has been updated.
        This function MUST return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` (i.e. 0xf23a6e61) if it accepts the transfer.
        This function MUST revert if it rejects the transfer.
        Return of any other value than the prescribed keccak256 generated value MUST result in the transaction being reverted by the caller.
        @param _operator  The address which initiated the transfer (i.e. msg.sender)
        @param _from      The address which previously owned the token
        @param _id        The ID of the token being transferred
        @param _value     The amount of tokens being transferred
        @param _data      Additional data with no specified format
        @return           `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
    */
    function onERC1155Received(address _operator, address _from, uint256 _id, uint256 _value, bytes calldata _data) external returns(bytes4);

    /**
        @notice Handle the receipt of multiple ERC1155 token types.
        @dev An ERC1155-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeBatchTransferFrom` after the balances have been updated.
        This function MUST return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` (i.e. 0xbc197c81) if it accepts the transfer(s).
        This function MUST revert if it rejects the transfer(s).
        Return of any other value than the prescribed keccak256 generated value MUST result in the transaction being reverted by the caller.
        @param _operator  The address which initiated the batch transfer (i.e. msg.sender)
        @param _from      The address which previously owned the token
        @param _ids       An array containing ids of each token being transferred (order and length must match _values array)
        @param _values    An array containing amounts of each token being transferred (order and length must match _ids array)
        @param _data      Additional data with no specified format
        @return           `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
    */
    function onERC1155BatchReceived(address _operator, address _from, uint256[] calldata _ids, uint256[] calldata _values, bytes calldata _data) external returns(bytes4);
}

contract TokenReceiverHooks is IERC721Receiver, IERC1155TokenReceiver {

    /**
     *  ERC721
     */

    /**
     * @notice Handle the receipt of an NFT
     * @dev The ERC721 smart contract calls this function on the recipient
     * after a {IERC721-safeTransferFrom}. This function MUST return the function selector,
     * otherwise the caller will revert the transaction. The selector to be
     * returned can be obtained as `this.onERC721Received.selector`. This
     * function MAY throw to revert and reject the transfer.
     * Note: the ERC721 contract address is always the message sender.
     * param operator The address which called `safeTransferFrom` function
     * param from The address which previously owned the token
     * param tokenId The NFT identifier which is being transferred
     * param data Additional data with no specified format
     * @return bytes4 `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`
     */
    function onERC721Received(address, address, uint256, bytes memory) public returns (bytes4) {
        return this.onERC721Received.selector;
    }

    /**
     *  ERC1155
     */

    function onERC1155Received(address, address, uint256, uint256, bytes calldata) external returns(bytes4) {
        return this.onERC1155Received.selector;
    }

    /**
     * @notice Handle the receipt of multiple ERC1155 token types.
     * @dev An ERC1155-compliant smart contract MUST call this function on the token recipient contract, at the end of a `safeBatchTransferFrom` after the balances have been updated.
     * This function MUST return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` (i.e. 0xbc197c81) if it accepts the transfer(s).
     * This function MUST revert if it rejects the transfer(s).
     * Return of any other value than the prescribed keccak256 generated value MUST result in the transaction being reverted by the caller.
     * param _operator  The address which initiated the batch transfer (i.e. msg.sender)
     * param _from      The address which previously owned the token
     * param _ids       An array containing ids of each token being transferred (order and length must match _values array)
     * param _values    An array containing amounts of each token being transferred (order and length must match _ids array)
     * param _data      Additional data with no specified format
     * @return           `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
     */
    function onERC1155BatchReceived(address, address, uint256[] calldata, uint256[] calldata, bytes calldata) external returns(bytes4) {
        return this.onERC1155BatchReceived.selector;
    }

}

contract IERC20 {
    function balanceOf(address account) external returns (uint256);
    function transfer(address recipient, uint256 amount) external returns (bool);
}

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 * 
 * This contract is from openzeppelin-solidity 2.4.0
 */
library ECDSA {
    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * NOTE: This call _does not revert_ if the signature is invalid, or
     * if the signer is otherwise unable to be retrieved. In those scenarios,
     * the zero address is returned.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        // Check the signature length
        if (signature.length != 65) {
            return (address(0));
        }

        // Divide the signature in r, s and v variables
        bytes32 r;
        bytes32 s;
        uint8 v;

        // ecrecover takes the signature parameters, and the only way to get them
        // currently is to use assembly.
        // solhint-disable-next-line no-inline-assembly
        assembly {
            r := mload(add(signature, 0x20))
            s := mload(add(signature, 0x40))
            v := byte(0, mload(add(signature, 0x60)))
        }

        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return address(0);
        }

        if (v != 27 && v != 28) {
            return address(0);
        }

        // If the signature is valid (and not malleable), return the signer address
        return ecrecover(hash, v, r, s);
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * replicates the behavior of the
     * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_sign`]
     * JSON-RPC method.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }
}

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 *
 * This contract is from openzeppelin-solidity 2.4.0
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     * - Subtraction cannot overflow.
     *
     * _Available since v2.4.0._
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     *
     * _Available since v2.4.0._
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     * - The divisor cannot be zero.
     *
     * _Available since v2.4.0._
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

/*
 * @title Solidity Bytes Arrays Utils
 * @author Gonçalo Sá <[email protected]>
 *
 * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.
 *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.
 */
library BytesLib {
    function concat(
        bytes memory _preBytes,
        bytes memory _postBytes
    )
        internal
        pure
        returns (bytes memory)
    {
        bytes memory tempBytes;

        assembly {
            // Get a location of some free memory and store it in tempBytes as
            // Solidity does for memory variables.
            tempBytes := mload(0x40)

            // Store the length of the first bytes array at the beginning of
            // the memory for tempBytes.
            let length := mload(_preBytes)
            mstore(tempBytes, length)

            // Maintain a memory counter for the current write location in the
            // temp bytes array by adding the 32 bytes for the array length to
            // the starting location.
            let mc := add(tempBytes, 0x20)
            // Stop copying when the memory counter reaches the length of the
            // first bytes array.
            let end := add(mc, length)

            for {
                // Initialize a copy counter to the start of the _preBytes data,
                // 32 bytes into its memory.
                let cc := add(_preBytes, 0x20)
            } lt(mc, end) {
                // Increase both counters by 32 bytes each iteration.
                mc := add(mc, 0x20)
                cc := add(cc, 0x20)
            } {
                // Write the _preBytes data into the tempBytes memory 32 bytes
                // at a time.
                mstore(mc, mload(cc))
            }

            // Add the length of _postBytes to the current length of tempBytes
            // and store it as the new length in the first 32 bytes of the
            // tempBytes memory.
            length := mload(_postBytes)
            mstore(tempBytes, add(length, mload(tempBytes)))

            // Move the memory counter back from a multiple of 0x20 to the
            // actual end of the _preBytes data.
            mc := end
            // Stop copying when the memory counter reaches the new combined
            // length of the arrays.
            end := add(mc, length)

            for {
                let cc := add(_postBytes, 0x20)
            } lt(mc, end) {
                mc := add(mc, 0x20)
                cc := add(cc, 0x20)
            } {
                mstore(mc, mload(cc))
            }

            // Update the free-memory pointer by padding our last write location
            // to 32 bytes: add 31 bytes to the end of tempBytes to move to the
            // next 32 byte block, then round down to the nearest multiple of
            // 32. If the sum of the length of the two arrays is zero then add 
            // one before rounding down to leave a blank 32 bytes (the length block with 0).
            mstore(0x40, and(
              add(add(end, iszero(add(length, mload(_preBytes)))), 31),
              not(31) // Round down to the nearest 32 bytes.
            ))
        }

        return tempBytes;
    }

    function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal {
        assembly {
            // Read the first 32 bytes of _preBytes storage, which is the length
            // of the array. (We don't need to use the offset into the slot
            // because arrays use the entire slot.)
            let fslot := sload(_preBytes_slot)
            // Arrays of 31 bytes or less have an even value in their slot,
            // while longer arrays have an odd value. The actual length is
            // the slot divided by two for odd values, and the lowest order
            // byte divided by two for even values.
            // If the slot is even, bitwise and the slot with 255 and divide by
            // two to get the length. If the slot is odd, bitwise and the slot
            // with -1 and divide by two.
            let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
            let mlength := mload(_postBytes)
            let newlength := add(slength, mlength)
            // slength can contain both the length and contents of the array
            // if length < 32 bytes so let's prepare for that
            // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
            switch add(lt(slength, 32), lt(newlength, 32))
            case 2 {
                // Since the new array still fits in the slot, we just need to
                // update the contents of the slot.
                // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length
                sstore(
                    _preBytes_slot,
                    // all the modifications to the slot are inside this
                    // next block
                    add(
                        // we can just add to the slot contents because the
                        // bytes we want to change are the LSBs
                        fslot,
                        add(
                            mul(
                                div(
                                    // load the bytes from memory
                                    mload(add(_postBytes, 0x20)),
                                    // zero all bytes to the right
                                    exp(0x100, sub(32, mlength))
                                ),
                                // and now shift left the number of bytes to
                                // leave space for the length in the slot
                                exp(0x100, sub(32, newlength))
                            ),
                            // increase length by the double of the memory
                            // bytes length
                            mul(mlength, 2)
                        )
                    )
                )
            }
            case 1 {
                // The stored value fits in the slot, but the combined value
                // will exceed it.
                // get the keccak hash to get the contents of the array
                mstore(0x0, _preBytes_slot)
                let sc := add(keccak256(0x0, 0x20), div(slength, 32))

                // save new length
                sstore(_preBytes_slot, add(mul(newlength, 2), 1))

                // The contents of the _postBytes array start 32 bytes into
                // the structure. Our first read should obtain the `submod`
                // bytes that can fit into the unused space in the last word
                // of the stored array. To get this, we read 32 bytes starting
                // from `submod`, so the data we read overlaps with the array
                // contents by `submod` bytes. Masking the lowest-order
                // `submod` bytes allows us to add that value directly to the
                // stored value.

                let submod := sub(32, slength)
                let mc := add(_postBytes, submod)
                let end := add(_postBytes, mlength)
                let mask := sub(exp(0x100, submod), 1)

                sstore(
                    sc,
                    add(
                        and(
                            fslot,
                            0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00
                        ),
                        and(mload(mc), mask)
                    )
                )

                for {
                    mc := add(mc, 0x20)
                    sc := add(sc, 1)
                } lt(mc, end) {
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } {
                    sstore(sc, mload(mc))
                }

                mask := exp(0x100, sub(mc, end))

                sstore(sc, mul(div(mload(mc), mask), mask))
            }
            default {
                // get the keccak hash to get the contents of the array
                mstore(0x0, _preBytes_slot)
                // Start copying to the last used word of the stored array.
                let sc := add(keccak256(0x0, 0x20), div(slength, 32))

                // save new length
                sstore(_preBytes_slot, add(mul(newlength, 2), 1))

                // Copy over the first `submod` bytes of the new data as in
                // case 1 above.
                let slengthmod := mod(slength, 32)
                let mlengthmod := mod(mlength, 32)
                let submod := sub(32, slengthmod)
                let mc := add(_postBytes, submod)
                let end := add(_postBytes, mlength)
                let mask := sub(exp(0x100, submod), 1)

                sstore(sc, add(sload(sc), and(mload(mc), mask)))
                
                for { 
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } lt(mc, end) {
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } {
                    sstore(sc, mload(mc))
                }

                mask := exp(0x100, sub(mc, end))

                sstore(sc, mul(div(mload(mc), mask), mask))
            }
        }
    }

    function slice(
        bytes memory _bytes,
        uint _start,
        uint _length
    )
        internal
        pure
        returns (bytes memory)
    {
        require(_bytes.length >= (_start + _length));

        bytes memory tempBytes;

        assembly {
            switch iszero(_length)
            case 0 {
                // Get a location of some free memory and store it in tempBytes as
                // Solidity does for memory variables.
                tempBytes := mload(0x40)

                // The first word of the slice result is potentially a partial
                // word read from the original array. To read it, we calculate
                // the length of that partial word and start copying that many
                // bytes into the array. The first word we copy will start with
                // data we don't care about, but the last `lengthmod` bytes will
                // land at the beginning of the contents of the new array. When
                // we're done copying, we overwrite the full first word with
                // the actual length of the slice.
                let lengthmod := and(_length, 31)

                // The multiplication in the next line is necessary
                // because when slicing multiples of 32 bytes (lengthmod == 0)
                // the following copy loop was copying the origin's length
                // and then ending prematurely not copying everything it should.
                let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
                let end := add(mc, _length)

                for {
                    // The multiplication in the next line has the same exact purpose
                    // as the one above.
                    let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)
                } lt(mc, end) {
                    mc := add(mc, 0x20)
                    cc := add(cc, 0x20)
                } {
                    mstore(mc, mload(cc))
                }

                mstore(tempBytes, _length)

                //update free-memory pointer
                //allocating the array padded to 32 bytes like the compiler does now
                mstore(0x40, and(add(mc, 31), not(31)))
            }
            //if we want a zero-length slice let's just return a zero-length array
            default {
                tempBytes := mload(0x40)

                mstore(0x40, add(tempBytes, 0x20))
            }
        }

        return tempBytes;
    }

    function toAddress(bytes memory _bytes, uint _start) internal  pure returns (address) {
        require(_bytes.length >= (_start + 20));
        address tempAddress;

        assembly {
            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
        }

        return tempAddress;
    }

    function toUint8(bytes memory _bytes, uint _start) internal  pure returns (uint8) {
        require(_bytes.length >= (_start + 1));
        uint8 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x1), _start))
        }

        return tempUint;
    }

    function toUint16(bytes memory _bytes, uint _start) internal  pure returns (uint16) {
        require(_bytes.length >= (_start + 2));
        uint16 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x2), _start))
        }

        return tempUint;
    }

    function toUint32(bytes memory _bytes, uint _start) internal  pure returns (uint32) {
        require(_bytes.length >= (_start + 4));
        uint32 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x4), _start))
        }

        return tempUint;
    }

    function toUint64(bytes memory _bytes, uint _start) internal  pure returns (uint64) {
        require(_bytes.length >= (_start + 8));
        uint64 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x8), _start))
        }

        return tempUint;
    }

    function toUint96(bytes memory _bytes, uint _start) internal  pure returns (uint96) {
        require(_bytes.length >= (_start + 12));
        uint96 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0xc), _start))
        }

        return tempUint;
    }

    function toUint128(bytes memory _bytes, uint _start) internal  pure returns (uint128) {
        require(_bytes.length >= (_start + 16));
        uint128 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x10), _start))
        }

        return tempUint;
    }

    function toUint(bytes memory _bytes, uint _start) internal  pure returns (uint256) {
        require(_bytes.length >= (_start + 32));
        uint256 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x20), _start))
        }

        return tempUint;
    }

    function toBytes32(bytes memory _bytes, uint _start) internal  pure returns (bytes32) {
        require(_bytes.length >= (_start + 32));
        bytes32 tempBytes32;

        assembly {
            tempBytes32 := mload(add(add(_bytes, 0x20), _start))
        }

        return tempBytes32;
    }

    function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) {
        bool success = true;

        assembly {
            let length := mload(_preBytes)

            // if lengths don't match the arrays are not equal
            switch eq(length, mload(_postBytes))
            case 1 {
                // cb is a circuit breaker in the for loop since there's
                //  no said feature for inline assembly loops
                // cb = 1 - don't breaker
                // cb = 0 - break
                let cb := 1

                let mc := add(_preBytes, 0x20)
                let end := add(mc, length)

                for {
                    let cc := add(_postBytes, 0x20)
                // the next line is the loop condition:
                // while(uint(mc < end) + cb == 2)
                } eq(add(lt(mc, end), cb), 2) {
                    mc := add(mc, 0x20)
                    cc := add(cc, 0x20)
                } {
                    // if any of these checks fails then arrays are not equal
                    if iszero(eq(mload(mc), mload(cc))) {
                        // unsuccess:
                        success := 0
                        cb := 0
                    }
                }
            }
            default {
                // unsuccess:
                success := 0
            }
        }

        return success;
    }

    function equalStorage(
        bytes storage _preBytes,
        bytes memory _postBytes
    )
        internal
        view
        returns (bool)
    {
        bool success = true;

        assembly {
            // we know _preBytes_offset is 0
            let fslot := sload(_preBytes_slot)
            // Decode the length of the stored array like in concatStorage().
            let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
            let mlength := mload(_postBytes)

            // if lengths don't match the arrays are not equal
            switch eq(slength, mlength)
            case 1 {
                // slength can contain both the length and contents of the array
                // if length < 32 bytes so let's prepare for that
                // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
                if iszero(iszero(slength)) {
                    switch lt(slength, 32)
                    case 1 {
                        // blank the last byte which is the length
                        fslot := mul(div(fslot, 0x100), 0x100)

                        if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) {
                            // unsuccess:
                            success := 0
                        }
                    }
                    default {
                        // cb is a circuit breaker in the for loop since there's
                        //  no said feature for inline assembly loops
                        // cb = 1 - don't breaker
                        // cb = 0 - break
                        let cb := 1

                        // get the keccak hash to get the contents of the array
                        mstore(0x0, _preBytes_slot)
                        let sc := keccak256(0x0, 0x20)

                        let mc := add(_postBytes, 0x20)
                        let end := add(mc, mlength)

                        // the next line is the loop condition:
                        // while(uint(mc < end) + cb == 2)
                        for {} eq(add(lt(mc, end), cb), 2) {
                            sc := add(sc, 1)
                            mc := add(mc, 0x20)
                        } {
                            if iszero(eq(sload(sc), mload(mc))) {
                                // unsuccess:
                                success := 0
                                cb := 0
                            }
                        }
                    }
                }
            }
            default {
                // unsuccess:
                success := 0
            }
        }

        return success;
    }
}

/**
 * @title BaseAccount
 * @author Authereum Labs, Inc.
 * @dev Base account contract. Performs most of the functionality
 * @dev of an Authereum account contract.
 */
contract BaseAccount is AccountState, AccountInitialize, TokenReceiverHooks {
    using SafeMath for uint256;
    using ECDSA for bytes32;
    using BytesLib for bytes;

    // Include a CHAIN_ID const
    uint256 constant private CHAIN_ID = 1;

    modifier onlySelf {
        require(msg.sender == address(this), "BA: Only self allowed");
        _;
    }

    modifier onlyAuthKeySender {
        require(_isValidAuthKey(msg.sender), "BA: Auth key is invalid");
        _;
    }

    modifier onlyAuthKeySenderOrSelf {
        require(_isValidAuthKey(msg.sender) || msg.sender == address(this), "BA: Auth key or self is invalid");
        _;
    }

    // Initialize logic contract via the constructor so it does not need to be done manually
    // after the deployment of the logic contract. Using max uint ensures that the true
    // lastInitializedVersion is never reached.
    constructor () public {
        lastInitializedVersion = uint256(-1);
    }

    // This is required for funds sent to this contract
    function () external payable {}

    /**
     *  Getters
     */

    /// @dev Get the chain ID constant
    /// @return The chain id
    function getChainId() public pure returns (uint256) {
        return CHAIN_ID;
    }

    /**
     *  Public functions
     */

    /// @dev Add an auth key to the list of auth keys
    /// @param _authKey Address of the auth key to add
    function addAuthKey(address _authKey) external onlyAuthKeySenderOrSelf {
        require(authKeys[_authKey] == false, "BA: Auth key already added");
        authKeys[_authKey] = true;
        numAuthKeys += 1;
        emit AuthKeyAdded(_authKey);
    }

    /// @dev Remove an auth key from the list of auth keys
    /// @param _authKey Address of the auth key to remove
    function removeAuthKey(address _authKey) external onlyAuthKeySenderOrSelf {
        require(authKeys[_authKey] == true, "BA: Auth key not yet added");
        require(numAuthKeys > 1, "BA: Cannot remove last auth key");
        authKeys[_authKey] = false;
        numAuthKeys -= 1;
        emit AuthKeyRemoved(_authKey);
    }

    /**
     *  Internal functions
     */

    /// @dev Check if an auth key is valid
    /// @param _authKey Address of the auth key to validate
    /// @return True if the auth key is valid
    function _isValidAuthKey(address _authKey) internal view returns (bool) {
        return authKeys[_authKey];
    }

    /// @dev Execute a transaction without a refund
    /// @notice This is the transaction sent from the CBA
    /// @param _destination Destination of the transaction
    /// @param _value Value of the transaction
    /// @param _gasLimit Gas limit of the transaction
    /// @param _data Data of the transaction
    /// @return Response of the call
    function _executeTransaction(
        address _destination,
        uint256 _value,
        uint256 _gasLimit,
        bytes memory _data
    )
        internal
        returns (bytes memory)
    {
        (bool success, bytes memory res) = _destination.call.gas(_gasLimit).value(_value)(_data);

        // Get the revert message of the call and revert with it if the call failed
        if (!success) {
            string memory _revertMsg = _getRevertMsg(res);
            revert(_revertMsg);
        }

        return res;
    }

    /// @dev Get the revert message from a call
    /// @notice This is needed in order to get the human-readable revert message from a call
    /// @param _res Response of the call
    /// @return Revert message string
    function _getRevertMsg(bytes memory _res) internal pure returns (string memory) {
        // If the _res length is less than 68, then the transaction failed silently (without a revert message)
        if (_res.length < 68) return 'BA: Transaction reverted silently';
        bytes memory revertData = _res.slice(4, _res.length - 4); // Remove the selector which is the first 4 bytes
        return abi.decode(revertData, (string)); // All that remains is the revert string
    }
}

contract IERC1271 {
    function isValidSignature(
        bytes memory _data,
        bytes memory _signature
    ) public view returns (bytes4 magicValue);
}

/**
 * @title ERC1271Account
 * @author Authereum Labs, Inc.
 * @dev Implements isValidSignature for ERC1271 compatibility
 */
contract ERC1271Account is IERC1271, BaseAccount {

    // NOTE: Valid magic value bytes4(keccak256("isValidSignature(bytes,bytes)")
    bytes4 constant private VALID_SIG = 0x20c13b0b;
    // NOTE: Invalid magic value
    bytes4 constant private INVALID_SIG = 0xffffffff;

    /**
     *  Public functions
     */

    /// @dev Check if a message and signature pair is valid
    /// @notice The _signature parameter can either be one auth key signature or it can
    /// @notice be a login key signature and an auth key signature (signed login key)
    /// @param _data Data that was signed
    /// @param _signature Signature(s) of the data. Either a single signature (login) or two (login and auth)
    /// @return VALID_SIG or INVALID_SIG hex data
    function isValidSignature(
        bytes memory _data,
        bytes memory _signature
    )
        public
        view
        returns (bytes4)
    {
        if (_signature.length == 65) {
            return isValidAuthKeySignature(_data, _signature);
        } else if (_signature.length >= 130) {
            return isValidLoginKeySignature(_data, _signature);
        } else {
            revert("ERC1271: Invalid isValidSignature _signature length");
        }
    }

    /// @dev Check if a message and auth key signature pair is valid
    /// @param _data Data that was signed
    /// @param _signature Signature of the data signed by the authkey
    /// @return VALID_SIG or INVALID_SIG hex data
    function isValidAuthKeySignature(
        bytes memory _data,
        bytes memory _signature
    )
        public
        view
        returns (bytes4)
    {
        require(_signature.length == 65, "ERC1271: Invalid isValidAuthKeySignature _signature length");

        address authKeyAddress = _getEthSignedMessageHash(_data).recover(
            _signature
        );

        bytes4 magicValue = _isValidAuthKey(authKeyAddress) ? VALID_SIG : INVALID_SIG;
        return magicValue;
    }

    /// @dev Check if a message and login key signature pair is valid, as well as a signed login key by an auth key
    /// @param _data Message that was signed
    /// @param _signature Signature of the data. Signed msg data by the login key and signed login key by auth key
    /// @return VALID_SIG or INVALID_SIG hex data
    function isValidLoginKeySignature(
        bytes memory _data,
        bytes memory _signature
    )
        public
        view
        returns (bytes4)
    {
        require(_signature.length >= 130, "ERC1271: Invalid isValidLoginKeySignature _signature length");

        bytes memory msgHashSignature = _signature.slice(0, 65);
        bytes memory loginKeyAttestationSignature = _signature.slice(65, 65);
        uint256 restrictionDataLength = _signature.length.sub(130);
        bytes memory loginKeyRestrictionData = _signature.slice(130, restrictionDataLength);

        address _loginKeyAddress = _getEthSignedMessageHash(_data).recover(
            msgHashSignature
        );

        // NOTE: The OpenZeppelin toEthSignedMessageHash is used here (and not above)
        // NOTE: because the length is hard coded at 32 and we know that this will always
        // NOTE: be true for this line.
        bytes32 loginKeyAttestationMessageHash = keccak256(abi.encode(
            _loginKeyAddress, loginKeyRestrictionData
        )).toEthSignedMessageHash();

        address _authKeyAddress = loginKeyAttestationMessageHash.recover(
            loginKeyAttestationSignature
        );

        bytes4 magicValue = _isValidAuthKey(_authKeyAddress) ? VALID_SIG : INVALID_SIG;
        return magicValue;
    }

    /**
     *  Internal functions
     */

    /// @dev Adds ETH signed message prefix to bytes message and hashes it
    /// @param _data Bytes data before adding the prefix
    /// @return Prefixed and hashed message
    function _getEthSignedMessageHash(bytes memory _data) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", _uint2str(_data.length), _data));
    }

    /// @dev Convert uint to string
    /// @param _num Uint to be converted
    /// @return String equivalent of the uint
    function _uint2str(uint _num) private pure returns (string memory _uintAsString) {
        if (_num == 0) {
            return "0";
        }
        uint i = _num;
        uint j = _num;
        uint len;
        while (j != 0) {
            len++;
            j /= 10;
        }
        bytes memory bstr = new bytes(len);
        uint k = len - 1;
        while (i != 0) {
            bstr[k--] = byte(uint8(48 + i % 10));
            i /= 10;
        }
        return string(bstr);
    }
}

/**
 * @title BaseMetaTxAccount
 * @author Authereum Labs, Inc.
 * @dev Contract that lays the foundations for meta transactions
 * @dev are performed in this contract as well.
 */
contract BaseMetaTxAccount is BaseAccount {

    /**
     * Public functions
     */

    /// @dev Execute multiple meta transactions
    /// @notice This can only be called by self as a part of the atomic meta transaction
    /// @param _transactions Arrays of transaction data ([destination, value, gasLimit, data][...]...)
    /// @return The responses of the calls
    function executeMultipleMetaTransactions(bytes[] memory _transactions) public onlyAuthKeySenderOrSelf returns (bytes[] memory) {
        return _executeMultipleMetaTransactions(_transactions);
    }

    /**
     *  Internal functions
     */

    /// @dev Atomically execute a meta transaction
    /// @param _transactions Arrays of transaction data ([destination, value, gasLimit, data][...]...)
    /// @param _gasPrice Gas price set by the user
    /// @param _gasOverhead Gas overhead of the transa...

// [truncated — 69589 bytes total]

Read Contract

authKeys 0x5175ca5e → bool
authereumVersion 0x1f602092 → string
getChainId 0x3408e470 → uint256
isValidAuthKeySignature 0x40914b06 → bytes4
isValidLoginKeySignature 0xd59e3e98 → bytes4
isValidSignature 0x20c13b0b → bytes4
lastInitializedVersion 0x7e7fd66c → uint256
nonce 0xaffed0e0 → uint256
numAuthKeys 0xec5e319e → uint256

Write Contract 11 functions

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

addAuthKey 0x13f8c578
address _authKey
executeMultipleAuthKeyMetaTransactions 0x26aa4655
bytes[] _transactions
uint256 _gasPrice
uint256 _gasOverhead
address _feeTokenAddress
uint256 _feeTokenRate
bytes _transactionMessageHashSignature
returns: bytes[]
executeMultipleLoginKeyMetaTransactions 0xd5553b88
bytes[] _transactions
uint256 _gasPrice
uint256 _gasOverhead
bytes _loginKeyRestrictionsData
address _feeTokenAddress
uint256 _feeTokenRate
bytes _transactionMessageHashSignature
bytes _loginKeyAttestationSignature
returns: bytes[]
executeMultipleMetaTransactions 0x792c891f
bytes[] _transactions
returns: bytes[]
initializeV1 0x1b9a9f9e
address _authKey
initializeV2 0x5b4e128c
uint256 _deploymentCost
onERC1155BatchReceived 0xbc197c81
address
address
uint256[]
uint256[]
bytes
returns: bytes4
onERC1155Received 0xf23a6e61
address
address
uint256
uint256
bytes
returns: bytes4
onERC721Received 0x150b7a02
address
address
uint256
bytes
returns: bytes4
removeAuthKey 0x9565389e
address _authKey
upgradeToAndCall 0x4f1ef286
address _newImplementation
bytes _data

Recent Transactions

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