Cryo Explorer Ethereum Mainnet

Address Contract Verified

Address 0x99054220d02acc8C608EE9dF7d5909Eb5A5DD7fb
Balance 0 ETH
Nonce 2
Code Size 23858 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

23858 bytes
0x6080604052600436106101c8575f3560e01c8063715018a6116100f2578063a8b0898211610092578063d03153aa11610062578063d03153aa146104f0578063efda182d14610505578063f2fde38b14610524578063f887ea4014610543575f5ffd5b8063a8b0898214610489578063b7c6b7c8146104a8578063c3ef17f3146104bd578063ccba2ddb146104dc575f5ffd5b80638da5cb5b116100cd5780638da5cb5b146104165780638ffb62d2146104345780639d159568146104555780639d76ea581461046a575f5ffd5b8063715018a6146103ba5780637fcd0e8d146103ce578063857620e1146103e2575f5ffd5b80634177b66f1161016857806346ebbdb01161013857806346ebbdb01461035f5780634cdff2fe1461037357806354f2679a146103885780635e3be34d1461039b575f5ffd5b80634177b66f146102e457806342af18841461030d5780634348b59b1461032c578063452d003f14610340575f5ffd5b80631b51fbb1116101a35780631b51fbb1146102275780631baaf4bd1461026157806324cc076614610284578063392e53cd146102bb575f5ffd5b80630a0a4189146101d35780630f9da743146101f4578063186e2d7714610213575f5ffd5b366101cf57005b5f5ffd5b3480156101de575f5ffd5b506101f26101ed366004612b1e565b610562565b005b3480156101ff575f5ffd5b506101f261020e366004612b1e565b61072f565b34801561021e575f5ffd5b506101f26107da565b348015610232575f5ffd5b50610241600754600654600292565b604080519384526020840192909252908201526060015b60405180910390f35b34801561026c575f5ffd5b5061027660075481565b604051908152602001610258565b34801561028f575f5ffd5b506102a361029e366004612b1e565b610963565b6040516001600160a01b039091168152602001610258565b3480156102c6575f5ffd5b506005546102d49060ff1681565b6040519015158152602001610258565b3480156102ef575f5ffd5b506102f861098b565b60408051928352901515602083015201610258565b348015610318575f5ffd5b506101f2610327366004612b1e565b610999565b348015610337575f5ffd5b506101f2610a83565b34801561034b575f5ffd5b506101f261035a366004612b1e565b611057565b34801561036a575f5ffd5b50610276600281565b34801561037e575f5ffd5b5061027660085481565b6101f2610396366004612be6565b61121d565b3480156103a6575f5ffd5b506101f26103b5366004612b1e565b611c27565b3480156103c5575f5ffd5b506101f2611ce3565b3480156103d9575f5ffd5b506101f2611d1d565b3480156103ed575f5ffd5b506104016103fc366004612c64565b611ef3565b60408051928352602083019190915201610258565b348015610421575f5ffd5b505f546102a3906001600160a01b031681565b34801561043f575f5ffd5b5061044861216d565b6040516102589190612c8d565b348015610460575f5ffd5b5061027660095481565b348015610475575f5ffd5b506001546102a3906001600160a01b031681565b348015610494575f5ffd5b506002546102a3906001600160a01b031681565b3480156104b3575f5ffd5b50610276600a5481565b3480156104c8575f5ffd5b506101f26104d7366004612cd8565b6121cd565b3480156104e7575f5ffd5b50610276612310565b3480156104fb575f5ffd5b5061027660065481565b348015610510575f5ffd5b506101f261051f366004612cd8565b61231e565b34801561052f575f5ffd5b506101f261053e366004612d0f565b6128d4565b34801561054e575f5ffd5b506003546102a3906001600160a01b031681565b5f546001600160a01b031633146105945760405162461bcd60e51b815260040161058b90612d31565b60405180910390fd5b600554610100900460ff16156105bc5760405162461bcd60e51b815260040161058b90612d54565b6005805461ff0019166101001790556002546001600160a01b03166105f35760405162461bcd60e51b815260040161058b90612d81565b5f81116106125760405162461bcd60e51b815260040161058b90612da2565b5f61061b612966565b90508181101561063d5760405162461bcd60e51b815260040161058b90612dce565b60025460405163a9059cbb60e01b815261dead6004820181905260248201859052916001600160a01b03169063a9059cbb906044016020604051808303815f875af115801561068e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106b29190612e05565b6106ec5760405162461bcd60e51b815260206004820152600b60248201526a109d5c9b8819985a5b195960aa1b604482015260640161058b565b6040518381527f599e3c1445f5d3f97307a24763cc7d200c7c523b685562a5df07759410a411ec9060200160405180910390a150506005805461ff001916905550565b5f546001600160a01b031633146107585760405162461bcd60e51b815260040161058b90612d31565b603281111561079e5760405162461bcd60e51b81526020600482015260126024820152710a8ded8cae4c2dcc6ca40e8dede40d0d2ced60731b604482015260640161058b565b60068190556040518181527fa3370f7fc7573d713f27ae89ba2f193d4b43991622ff969b0475e2f911aacf1a906020015b60405180910390a150565b5f546001600160a01b031633146108035760405162461bcd60e51b815260040161058b90612d31565b600554610100900460ff161561082b5760405162461bcd60e51b815260040161058b90612d54565b6005805461ff001916610100179055478061087c5760405162461bcd60e51b815260206004820152601160248201527027379022aa24103a37903932b1b7bb32b960791b604482015260640161058b565b5f80546040516001600160a01b039091169083908381818185875af1925050503d805f81146108c6576040519150601f19603f3d011682016040523d82523d5f602084013e6108cb565b606091505b50509050806109125760405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b604482015260640161058b565b5f546040518381526001600160a01b03909116907f0923a1159e4557a4252f468d636ab7daefb6370b599dec7f60a961fa9fb58be7906020015b60405180910390a250506005805461ff0019169055565b60048181548110610972575f80fd5b5f918252602090912001546001600160a01b0316905081565b600a545f815a101590509091565b5f546001600160a01b031633146109c25760405162461bcd60e51b815260040161058b90612d31565b600f811015610a085760405162461bcd60e51b8152602060048201526012602482015271111958591b1a5b99481d1bdbc81cda1bdc9d60721b604482015260640161058b565b610258811115610a4e5760405162461bcd60e51b8152602060048201526011602482015270446561646c696e6520746f6f206c6f6e6760781b604482015260640161058b565b60088190556040518181527fdb00f0341e024be397e058a193a27b85cc3e7f921640be77ddf155c9f8d37c5a906020016107cf565b6001546001600160a01b03163314610ad35760405162461bcd60e51b815260206004820152601360248201527213db9b1e481d1bdad95b8818d85b8818d85b1b606a1b604482015260640161058b565b6001546001600160a01b0316610b235760405162461bcd60e51b8152602060048201526015602482015274151bdad95b881b9bdd081a5b9a5d1a585b1a5e9959605a1b604482015260640161058b565b600554610100900460ff1615610b4b5760405162461bcd60e51b815260040161058b90612d54565b6005805461ff001916610100179055475f819003610b69575061104a565b5f5a9050600954600a54610b7d9190612e38565b811015610bd5577f1796228003433d7e098ed8c6a104e057ae3bc44e514af8cce440a16d88a72bd681600954600a54610bb69190612e38565b6040805192835260208301919091520160405180910390a1505061104a565b5f5b6002811161104657479250825f03610bf15750505061104a565b5f60075482610c009190612e4b565b600654610c0d9190612e38565b90506032811115610c1c575060325b5f610c2785836129e7565b90505f60085442610c389190612e38565b90507fbd87b7fd36ca10216ecd84ec6b511a2b6a32701cc22007462dbe03a6954972dc610c66856001612e38565b604080519182526020820189905281018590526060810184905260800160405180910390a16001546040516370a0823160e01b81523060048201525f916001600160a01b0316906370a0823190602401602060405180830381865afa158015610cd1573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cf59190612e62565b60035460405163b6f9de9560e01b81529192506001600160a01b03169063b6f9de95908990610d2e908790600490309089908301612ebf565b5f604051808303818588803b158015610d45575f5ffd5b505af193505050508015610d57575060015b610e2b57610d63612ef3565b806308c379a003610de75750610d77612f0c565b80610d825750610de9565b6002861015610d95575050505050611034565b7fa1da5bd9d62e3afc7dab61bfacb9b20a2b09422413e8b005da62529623881fe888610dc2886001612e38565b6040805192835260208301919091520160405180910390a1505050505050505061104a565b505b3d808015610e12576040519150601f19603f3d011682016040523d82523d5f602084013e610e17565b606091505b506002861015610d95575050505050611034565b6001546040516370a0823160e01b81523060048201525f916001600160a01b0316906370a0823190602401602060405180830381865afa158015610e71573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e959190612e62565b90505f610ea28383612f90565b905084811015610ec45760405162461bcd60e51b815260040161058b90612fa3565b80156110265760015460405163a9059cbb60e01b815261dead6004820181905260248201849052916001600160a01b03169063a9059cbb906044016020604051808303815f875af1158015610f1b573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f3f9190612e05565b610f825760405162461bcd60e51b8152602060048201526014602482015273109d5c9b881d1c985b9cd9995c8819985a5b195960621b604482015260640161058b565b5f5a610f8e908b612f90565b90507f58a9be6ff5fc8bc43bfb8eef8aba0eadd1ca1f7f65402a356b623a5a31de300f8b8483610fbf8d6001612e38565b6040805194855260208501939093529183015260608201526080810189905260a0810188905260c00160405180910390a16040518381527f6ef4855b666dcc7884561072e4358b28dfe01feb1b7f4dcebc00e62d50394ac79060200160405180910390a150505b50505050505050505061104a565b8061103e81612fce565b915050610bd7565b5050505b6005805461ff0019169055565b5f546001600160a01b031633146110805760405162461bcd60e51b815260040161058b90612d31565b600554610100900460ff16156110a85760405162461bcd60e51b815260040161058b90612d54565b6005805461ff0019166101001790556002546001600160a01b03166110df5760405162461bcd60e51b815260040161058b90612d81565b5f81116110fe5760405162461bcd60e51b815260040161058b90612da2565b5f611107612966565b9050818110156111295760405162461bcd60e51b815260040161058b90612dce565b6002545f5460405163a9059cbb60e01b81526001600160a01b0391821660048201526024810185905291169063a9059cbb906044016020604051808303815f875af115801561117a573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061119e9190612e05565b6111df5760405162461bcd60e51b81526020600482015260126024820152711314081d1c985b9cd9995c8819985a5b195960721b604482015260640161058b565b5f546040518381526001600160a01b03909116907fd0f180543559f70d2d58da088e6bf2ffb4e5d8a40d4c0eda25612a2e1a4dd0bc9060200161094c565b5f546001600160a01b031633146112465760405162461bcd60e51b815260040161058b90612d31565b600554610100900460ff161561126e5760405162461bcd60e51b815260040161058b90612d54565b6005805461ff001981166101001790915560ff16156112c55760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b604482015260640161058b565b5f341161130d5760405162461bcd60e51b81526020600482015260166024820152754e6565642045544820666f72206c697175696469747960501b604482015260640161058b565b8282111561135d5760405162461bcd60e51b815260206004820152601760248201527f4c5020746f6b656e732065786365656420737570706c79000000000000000000604482015260640161058b565b5f82116113a45760405162461bcd60e51b815260206004820152601560248201527404c5020746f6b656e73206d757374206265203e203605c1b604482015260640161058b565b5f604051806020016113b590612b11565b6020820181038252601f19601f8201166040525090505f8686863060035f9054906101000a90046001600160a01b03166001600160a01b031663ad5c46486040518163ffffffff1660e01b8152600401602060405180830381865afa158015611420573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114449190612fe6565b60035f9054906101000a90046001600160a01b03166001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa158015611494573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114b89190612fe6565b6040516020016114cd9695949392919061302f565b60405160208183030381529060405290505f82826040516020016114f292919061309b565b60405160208183030381529060405290505f848251602084015ff59050803b611519575f5ffd5b6001600160a01b03811661156f5760405162461bcd60e51b815260206004820152601760248201527f546f6b656e206465706c6f796d656e74206661696c6564000000000000000000604482015260640161058b565b600180546001600160a01b0319166001600160a01b0383169081178255600480549192909181106115a2576115a26130b7565b5f918252602082200180546001600160a01b0319166001600160a01b0393909316929092179091556004805482906115dc576115dc6130b7565b5f918252602090912001546001600160a01b0316036116345760405162461bcd60e51b8152602060048201526014602482015273092dcecc2d8d2c840ae8aa89040d2dc40e0c2e8d60631b604482015260640161058b565b60018054600480546001600160a01b039092169290918110611658576116586130b7565b5f918252602090912001546001600160a01b0316146116b15760405162461bcd60e51b8152602060048201526015602482015274092dcecc2d8d2c840e8ded6cadc40d2dc40e0c2e8d605b1b604482015260640161058b565b7f479310ca8888d8a8ac0aa6365bc4df9c6b0a4c655b5b050dfdd4ed74e585d39060045f815481106116e5576116e56130b7565b5f91825260209091200154600480546001600160a01b03909216916001908110611711576117116130b7565b5f9182526020909120015460405161174892916001600160a01b0316906001600160a01b0392831681529116602082015260400190565b60405180910390a160015460035460405163095ea7b360e01b81526001600160a01b0391821660048201526024810189905291169063095ea7b3906044016020604051808303815f875af11580156117a2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117c69190612e05565b6118045760405162461bcd60e51b815260206004820152600f60248201526e105c1c1c9bdd985b0819985a5b1959608a1b604482015260640161058b565b6003546001545f91829182916001600160a01b039081169163f305d719913491168c606461183382605f612e4b565b61183d91906130cb565b606461184a34605f612e4b565b61185491906130cb565b30600854426118639190612e38565b6040518863ffffffff1660e01b8152600401611884969594939291906130ea565b60606040518083038185885af11580156118a0573d5f5f3e3d5ffd5b50505050506040513d601f19601f820116820180604052508101906118c59190613125565b9250925092505f831180156118d957505f82115b61191c5760405162461bcd60e51b8152602060048201526014602482015273131a5c5d5a591a5d1e481859190819985a5b195960621b604482015260640161058b565b5f81116119635760405162461bcd60e51b8152602060048201526015602482015274139bc81314081d1bdad95b9cc81c9958d95a5d9959605a1b604482015260640161058b565b60035f9054906101000a90046001600160a01b03166001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119b3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119d79190612fe6565b600154600354604080516315ab88c960e31b815290516001600160a01b039485169463e6a4390594811693169163ad5c46489160048083019260209291908290030181865afa158015611a2c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a509190612fe6565b6040516001600160e01b031960e085901b1681526001600160a01b03928316600482015291166024820152604401602060405180830381865afa158015611a99573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611abd9190612fe6565b600280546001600160a01b0319166001600160a01b03929092169182179055611b1f5760405162461bcd60e51b815260206004820152601460248201527314185a5c8818dc99585d1a5bdb8819985a5b195960621b604482015260640161058b565b60015460025460405163485cc95560e01b81526001600160a01b03918216600482015230602482015291169063485cc955906044015f604051808303815f87803b158015611b6b575f5ffd5b505af1158015611b7d573d5f5f3e3d5ffd5b50506005805460ff1916600190811790915560025490546040516001600160a01b039283169450911691507ff9a44e6db3fb6e0eb31c4013bda8c662fecef1768dd2412270cc8f8821cbccf3905f90a360408051848152602081018490529081018290527fd7f28048575eead8851d024ead087913957dfb4fd1a02b4d1573f5352a5a2be39060600160405180910390a150506005805461ff001916905550505050505050505050565b5f546001600160a01b03163314611c505760405162461bcd60e51b815260040161058b90612d31565b60018110158015611c625750600a8111155b611cae5760405162461bcd60e51b815260206004820152601960248201527f496e76616c696420736c69707061676520696e63726561736500000000000000604482015260640161058b565b60078190556040518181527f2d2fdcebdfe0f0fa3cc3d883df5b786570a00ef479f509a3a8a5503af08e5b6e906020016107cf565b5f546001600160a01b03163314611d0c5760405162461bcd60e51b815260040161058b90612d31565b5f80546001600160a01b0319169055565b5f546001600160a01b03163314611d465760405162461bcd60e51b815260040161058b90612d31565b600554610100900460ff1615611d6e5760405162461bcd60e51b815260040161058b90612d54565b6005805461ff0019166101001790556002546001600160a01b0316611da55760405162461bcd60e51b815260040161058b90612d81565b5f611dae612966565b90505f8111611dee5760405162461bcd60e51b815260206004820152600c60248201526b4e6f204c5020746f6b656e7360a01b604482015260640161058b565b6002545f5460405163a9059cbb60e01b81526001600160a01b0391821660048201526024810184905291169063a9059cbb906044016020604051808303815f875af1158015611e3f573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e639190612e05565b611ea45760405162461bcd60e51b81526020600482015260126024820152711314081d1c985b9cd9995c8819985a5b195960721b604482015260640161058b565b5f546040518281526001600160a01b03909116907fd0f180543559f70d2d58da088e6bf2ffb4e5d8a40d4c0eda25612a2e1a4dd0bc9060200160405180910390a2506005805461ff0019169055565b5f805481906001600160a01b03163314611f1f5760405162461bcd60e51b815260040161058b90612d31565b600554610100900460ff1615611f475760405162461bcd60e51b815260040161058b90612d54565b6005805461ff0019166101001790556002546001600160a01b0316611f7e5760405162461bcd60e51b815260040161058b90612d81565b5f8511611f9d5760405162461bcd60e51b815260040161058b90612da2565b5f611fa6612966565b905085811015611fc85760405162461bcd60e51b815260040161058b90612dce565b60025460035460405163095ea7b360e01b81526001600160a01b0391821660048201526024810189905291169063095ea7b3906044016020604051808303815f875af115801561201a573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061203e9190612e05565b61207f5760405162461bcd60e51b8152602060048201526012602482015271131408185c1c1c9bdd985b0819985a5b195960721b604482015260640161058b565b6003546001545f546008546001600160a01b03938416936302751cec938116928b928b928b9216906120b19042612e38565b6040518763ffffffff1660e01b81526004016120d2969594939291906130ea565b60408051808303815f875af11580156120ed573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121119190613150565b604080518381526020810183905290810189905291945092507fd7f28048575eead8851d024ead087913957dfb4fd1a02b4d1573f5352a5a2be39060600160405180910390a1506005805461ff00191690559094909350915050565b606060048054806020026020016040519081016040528092919081815260200182805480156121c357602002820191905f5260205f20905b81546001600160a01b031681526001909101906020018083116121a5575b5050505050905090565b5f546001600160a01b031633146121f65760405162461bcd60e51b815260040161058b90612d31565b61c35082101561223a5760405162461bcd60e51b815260206004820152600f60248201526e5265736572766520746f6f206c6f7760881b604482015260640161058b565b62030d408110156122815760405162461bcd60e51b8152602060048201526011602482015270476173206c696d697420746f6f206c6f7760781b604482015260640161058b565b6207a1208111156122c95760405162461bcd60e51b815260206004820152601260248201527108ec2e640d8d2dad2e840e8dede40d0d2ced60731b604482015260640161058b565b6009829055600a81905560408051838152602081018390527f6bd79799f132160c1d0959f0684be5841c1a56641de803805011bcd87c561d8c910160405180910390a15050565b5f612319612966565b905090565b5f546001600160a01b031633146123475760405162461bcd60e51b815260040161058b90612d31565b600554610100900460ff161561236f5760405162461bcd60e51b815260040161058b90612d54565b6005805461ff001916610100179055816123c25760405162461bcd60e51b8152602060048201526014602482015273125b9d985b1a59081b5a5b905b5bdd5b9d13dd5d60621b604482015260640161058b565b600f81101580156123d557506102588111155b6124145760405162461bcd60e51b815260206004820152601060248201526f496e76616c696420646561646c696e6560801b604482015260640161058b565b47806124575760405162461bcd60e51b81526020600482015260126024820152714e6f2045544820666f72206275796261636b60701b604482015260640161058b565b5f5a9050600a548110156124ad5760405162461bcd60e51b815260206004820152601960248201527f496e73756666696369656e74206761732070726f766964656400000000000000604482015260640161058b565b5f5b600281116128c157479250825f036124c9575050506128c5565b5f600754826124d89190612e4b565b6006546124e59190612e38565b905060328111156124f4575060325b5f821561250a5761250585836129e7565b61250c565b865b90505f6125198742612e38565b6001546040516370a0823160e01b81523060048201529192505f916001600160a01b03909116906370a0823190602401602060405180830381865afa158015612564573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125889190612e62565b60035460405163b6f9de9560e01b81529192506001600160a01b03169063b6f9de959089906125c1908790600490309089908301612ebf565b5f604051808303818588803b1580156125d8575f5ffd5b505af1935050505080156125ea575060015b6126e8577fbd87b7fd36ca10216ecd84ec6b511a2b6a32701cc22007462dbe03a6954972dc61261a866001612e38565b60408051918252602082018a905281018690526060810185905260800160405180910390a1600285036126e3577fa1da5bd9d62e3afc7dab61bfacb9b20a2b09422413e8b005da62529623881fe887612674876001612e38565b6040805192835260208301919091520160405180910390a160405162461bcd60e51b815260206004820152602660248201527f4d616e75616c207265747279206661696c656420616674657220616c6c20617460448201526574656d70747360d01b606482015260840161058b565b6128aa565b6001546040516370a0823160e01b81523060048201525f916001600160a01b0316906370a0823190602401602060405180830381865afa15801561272e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127529190612e62565b90505f61275f8383612f90565b9050848110156127815760405162461bcd60e51b815260040161058b90612fa3565b801561289c5760015460405163a9059cbb60e01b815261dead6004820181905260248201849052916001600160a01b03169063a9059cbb906044016020604051808303815f875af11580156127d8573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127fc9190612e05565b507f58a9be6ff5fc8bc43bfb8eef8aba0eadd1ca1f7f65402a356b623a5a31de300f8a835a61282b908d612f90565b6128368c6001612e38565b6040805194855260208501939093529183015260608201526080810188905260a0810187905260c00160405180910390a16040518281527f6ef4855b666dcc7884561072e4358b28dfe01feb1b7f4dcebc00e62d50394ac79060200160405180910390a1505b5050505050505050506128c5565b5050505080806128b990612fce565b9150506124af565b5050505b50506005805461ff0019169055565b5f546001600160a01b031633146128fd5760405162461bcd60e51b815260040161058b90612d31565b6001600160a01b0381166129455760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015260640161058b565b5f80546001600160a01b0319166001600160a01b0392909216919091179055565b6002545f906001600160a01b031661297d57505f90565b6002546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa1580156129c3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123199190612e62565b5f6032821115612a095760405162461bcd60e51b815260040161058b90612fa3565b60035460405163d06ca61f60e01b81525f916001600160a01b03169063d06ca61f90612a3b9087906004908101613172565b5f60405180830381865afa158015612a55573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052612a7c919081019061318a565b90505f81600181518110612a9257612a926130b7565b602002602001015190505f6064856064612aac9190612f90565b612ab69084612e4b565b612ac091906130cb565b90505f8111612b065760405162461bcd60e51b81526020600482015260126024820152714d696e20746f6b656e7320746f6f206c6f7760701b604482015260640161058b565b925050505b92915050565b612ac68061323783390190565b5f60208284031215612b2e575f5ffd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b601f8201601f1916810167ffffffffffffffff81118282101715612b6f57612b6f612b35565b6040525050565b5f82601f830112612b85575f5ffd5b813567ffffffffffffffff811115612b9f57612b9f612b35565b604051612bb6601f8301601f191660200182612b49565b818152846020838601011115612bca575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f5f5f5f60a08688031215612bfa575f5ffd5b853567ffffffffffffffff811115612c10575f5ffd5b612c1c88828901612b76565b955050602086013567ffffffffffffffff811115612c38575f5ffd5b612c4488828901612b76565b959895975050505060408401359360608101359360809091013592509050565b5f5f5f60608486031215612c76575f5ffd5b505081359360208301359350604090920135919050565b602080825282518282018190525f918401906040840190835b81811015612ccd5783516001600160a01b0316835260209384019390920191600101612ca6565b509095945050505050565b5f5f60408385031215612ce9575f5ffd5b50508035926020909101359150565b6001600160a01b0381168114612d0c575f5ffd5b50565b5f60208284031215612d1f575f5ffd5b8135612d2a81612cf8565b9392505050565b6020808252600990820152682737ba1037bbb732b960b91b604082015260600190565b6020808252601390820152721499595b9d1c985b98de4819195d1958dd1959606a1b604082015260600190565b6020808252600790820152662737903830b4b960c91b604082015260600190565b6020808252601290820152710416d6f756e74206d757374206265203e20360741b604082015260600190565b60208082526017908201527f496e73756666696369656e74204c502062616c616e6365000000000000000000604082015260600190565b5f60208284031215612e15575f5ffd5b81518015158114612d2a575f5ffd5b634e487b7160e01b5f52601160045260245ffd5b80820180821115612b0b57612b0b612e24565b8082028115828204841417612b0b57612b0b612e24565b5f60208284031215612e72575f5ffd5b5051919050565b5f8154808452602084019350825f5260205f205f5b82811015612eb55781546001600160a01b0316865260209095019460019182019101612e8e565b5093949350505050565b848152608060208201525f612ed76080830186612e79565b6001600160a01b03949094166040830152506060015292915050565b5f60033d1115612f095760045f5f3e505f5160e01c5b90565b5f60443d1015612f195790565b6040513d600319016004823e80513d602482011167ffffffffffffffff82111715612f4357505090565b808201805167ffffffffffffffff811115612f5f575050505090565b3d8401600319018282016020011115612f79575050505090565b612f8860208285010185612b49565b509392505050565b81810381811115612b0b57612b0b612e24565b6020808252601190820152700a6d8d2e0e0c2ceca40e8dede40d0d2ced607b1b604082015260600190565b5f60018201612fdf57612fdf612e24565b5060010190565b5f60208284031215612ff6575f5ffd5b8151612d2a81612cf8565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b60c081525f61304160c0830189613001565b82810360208401526130538189613001565b604084019790975250506001600160a01b039384166060820152918316608083015290911660a09091015292915050565b5f81518060208401855e5f93019283525090919050565b5f6130af6130a98386613084565b84613084565b949350505050565b634e487b7160e01b5f52603260045260245ffd5b5f826130e557634e487b7160e01b5f52601260045260245ffd5b500490565b6001600160a01b039687168152602081019590955260408501939093526060840191909152909216608082015260a081019190915260c00190565b5f5f5f60608486031215613137575f5ffd5b5050815160208301516040909301519094929350919050565b5f5f60408385031215613161575f5ffd5b505080516020909101519092909150565b828152604060208201525f6130af6040830184612e79565b5f6020828403121561319a575f5ffd5b815167ffffffffffffffff8111156131b0575f5ffd5b8201601f810184136131c0575f5ffd5b805167ffffffffffffffff8111156131da576131da612b35565b8060051b6040516131ee6020830182612b49565b918252602081840181019290810187841115613208575f5ffd5b6020850194505b8385101561322b5784518082526020958601959093500161320f565b50969550505050505056fe60e06040526004600555600460065562086470600955348015610020575f5ffd5b50604051612ac6380380612ac683398101604081905261003f916102b5565b6001600160a01b03831661008c5760405162461bcd60e51b815260206004820152600f60248201526e24b73b30b634b21036b0b730b3b2b960891b60448201526064015b60405180910390fd5b6001600160a01b0382166100d15760405162461bcd60e51b815260206004820152600c60248201526b092dcecc2d8d2c840ae8aa8960a31b6044820152606401610083565b6001600160a01b0381166101195760405162461bcd60e51b815260206004820152600f60248201526e496e76616c696420666163746f727960881b6044820152606401610083565b5f61012487826103d6565b50600161013186826103d6565b506002849055600a80546001600160a01b0319166001600160a01b03858116919091179091553360c052828116608052811660a05261017261271085610490565b6007556001600e8190556001600160a01b0384165f818152600360209081526040808320899055600c8252808320805460ff19908116871790915530845281842080549091169095179094559251878152919290917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050505050506104af565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112610220575f5ffd5b81516001600160401b03811115610239576102396101fd565b604051601f8201601f19908116603f011681016001600160401b0381118282101715610267576102676101fd565b60405281815283820160200185101561027e575f5ffd5b8160208501602083015e5f918101602001919091529392505050565b80516001600160a01b03811681146102b0575f5ffd5b919050565b5f5f5f5f5f5f60c087890312156102ca575f5ffd5b86516001600160401b038111156102df575f5ffd5b6102eb89828a01610211565b602089015190975090506001600160401b03811115610308575f5ffd5b61031489828a01610211565b9550506040870151935061032a6060880161029a565b92506103386080880161029a565b915061034660a0880161029a565b90509295509295509295565b600181811c9082168061036657607f821691505b60208210810361038457634e487b7160e01b5f52602260045260245ffd5b50919050565b601f8211156103d157805f5260205f20601f840160051c810160208510156103af5750805b601f840160051c820191505b818110156103ce575f81556001016103bb565b50505b505050565b81516001600160401b038111156103ef576103ef6101fd565b610403816103fd8454610352565b8461038a565b6020601f821160018114610435575f831561041e5750848201515b5f19600385901b1c1916600184901b1784556103ce565b5f84815260208120601f198516915b828110156104645787850151825560209485019460019092019101610444565b508482101561048157868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b5f826104aa57634e487b7160e01b5f52601260045260245ffd5b500490565b60805160a05160c0516125b861050e5f395f50505f818161055701528181610d4a01528181611aa90152611c2901525f81816104f001528181610cd601528181610d11015281816119a7015281816119e20152611a7f01526125b85ff3fe6080604052600436106101de575f3560e01c806395d89b41116100fd578063c45a015511610092578063e89d4d7d11610062578063e89d4d7d146105f1578063f1a8c48314610605578063f8b91abe14610624578063fc73854914610638575f5ffd5b8063c45a015514610546578063cc1776d314610579578063d83567ab1461058e578063dd62ed3e146105ad575f5ffd5b8063ab6a8b1c116100cd578063ab6a8b1c146104c0578063ad5c4648146104df578063b7c6b7c814610512578063c024666814610527575f5ffd5b806395d89b4114610459578063a367f5c21461046d578063a8b0898214610482578063a9059cbb146104a1575f5ffd5b80634ada218b1161017357806370a082311161014357806370a08231146103a95780638a8c523c146103dd5780638b8dbfd4146103f15780638d32ca8b14610422575f5ffd5b80634ada218b146102fe5780634f7041a5146103175780635342acb41461032c57806356b35b0e1461035a575f5ffd5b8063186e2d77116101ae578063186e2d771461028657806323b872dd1461029a578063313ce567146102b9578063485cc955146102df575f5ffd5b806306fdde03146101e9578063095ea7b3146102135780630d0c278f1461024257806318160ddd14610263575f5ffd5b366101e557005b5f5ffd5b3480156101f4575f5ffd5b506101fd61064c565b60405161020a919061219b565b60405180910390f35b34801561021e575f5ffd5b5061023261022d3660046121cb565b6106d7565b604051901515815260200161020a565b34801561024d575f5ffd5b5061026161025c3660046121f5565b6106ed565b005b34801561026e575f5ffd5b5061027860025481565b60405190815260200161020a565b348015610291575f5ffd5b506102616107eb565b3480156102a5575f5ffd5b506102326102b436600461220c565b6108f1565b3480156102c4575f5ffd5b506102cd601281565b60405160ff909116815260200161020a565b3480156102ea575f5ffd5b506102616102f936600461224a565b610992565b348015610309575f5ffd5b50600d546102329060ff1681565b348015610322575f5ffd5b5061027860055481565b348015610337575f5ffd5b50610232610346366004612281565b600c6020525f908152604090205460ff1681565b348015610365575f5ffd5b5061036e610aff565b604080516001600160a01b0396871681529486166020860152928516928401929092529092166060820152901515608082015260a00161020a565b3480156103b4575f5ffd5b506102786103c3366004612281565b6001600160a01b03165f9081526003602052604090205490565b3480156103e8575f5ffd5b50610261610da4565b3480156103fc575f5ffd5b50610405610e6a565b60408051931515845260208401929092529082015260600161020a565b34801561042d575f5ffd5b50600a54610441906001600160a01b031681565b6040516001600160a01b03909116815260200161020a565b348015610464575f5ffd5b506101fd610e8d565b348015610478575f5ffd5b5061027860075481565b34801561048d575f5ffd5b50600b54610441906001600160a01b031681565b3480156104ac575f5ffd5b506102326104bb3660046121cb565b610e9a565b3480156104cb575f5ffd5b506102616104da36600461229c565b610ea6565b3480156104ea575f5ffd5b506104417f000000000000000000000000000000000000000000000000000000000000000081565b34801561051d575f5ffd5b5061027860095481565b348015610532575f5ffd5b506102616105413660046122bc565b610f28565b348015610551575f5ffd5b506104417f000000000000000000000000000000000000000000000000000000000000000081565b348015610584575f5ffd5b5061027860065481565b348015610599575f5ffd5b506102616105a83660046121f5565b610f7c565b3480156105b8575f5ffd5b506102786105c736600461224a565b6001600160a01b039182165f90815260046020908152604080832093909416825291909152205490565b3480156105fc575f5ffd5b50610261611031565b348015610610575f5ffd5b5061026161061f3660046121cb565b611091565b34801561062f575f5ffd5b506102616111c8565b348015610643575f5ffd5b50610261611204565b5f8054610658906122ec565b80601f0160208091040260200160405190810160405280929190818152602001828054610684906122ec565b80156106cf5780601f106106a6576101008083540402835291602001916106cf565b820191905f5260205f20905b8154815290600101906020018083116106b257829003601f168201915b505050505081565b5f6106e33384846112cc565b5060015b92915050565b600a546001600160a01b031633146107205760405162461bcd60e51b815260040161071790612324565b60405180910390fd5b62061a808110156107675760405162461bcd60e51b8152602060048201526011602482015270476173206c696d697420746f6f206c6f7760781b6044820152606401610717565b620f42408111156107af5760405162461bcd60e51b815260206004820152601260248201527108ec2e640d8d2dad2e840e8dede40d0d2ced60731b6044820152606401610717565b60098190556040518181527fc55bc88e18ef7c8487ab567aff00704b2c2a16637de3c20160452e108e167e4c906020015b60405180910390a150565b600a546001600160a01b031633146108155760405162461bcd60e51b815260040161071790612324565b47806108575760405162461bcd60e51b815260206004820152601160248201527027379022aa24103a37903932b1b7bb32b960791b6044820152606401610717565b600a546040515f916001600160a01b03169083908381818185875af1925050503d805f81146108a1576040519150601f19603f3d011682016040523d82523d5f602084013e6108a6565b606091505b50509050806108ed5760405162461bcd60e51b8152602060048201526013602482015272115512081d1c985b9cd9995c8819985a5b1959606a1b6044820152606401610717565b5050565b5f6108fd8484846113d8565b6001600160a01b0384165f9081526004602090815260408083203384529091529020548281101561097a5760405162461bcd60e51b815260206004820152602160248201527f5472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636044820152606560f81b6064820152608401610717565b61098785338584036112cc565b506001949350505050565b600a546001600160a01b031633146109bc5760405162461bcd60e51b815260040161071790612324565b600b546001600160a01b031615610a0b5760405162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b6044820152606401610717565b6001600160a01b038216610a585760405162461bcd60e51b8152602060048201526014602482015273496e76616c69642070616972206164647265737360601b6044820152606401610717565b6001600160a01b038116610aae5760405162461bcd60e51b815260206004820152601760248201527f496e76616c6964206d616e6167657220616464726573730000000000000000006044820152606401610717565b610ab7826117e4565b600b80546001600160a01b039384166001600160a01b03199182168117909255600a8054939094169216919091179091555f908152600c60205260409020805460ff19169055565b600b545f9081908190819081906001600160a01b0316610b2c57505f935083925082915081905080610d9d565b600b5460408051630dfe168160e01b815290516001600160a01b03909216918291630dfe16819160048083019260209291908290030181865afa925050508015610b93575060408051601f3d908101601f19168201909252610b909181019061234a565b60015b610bb6575050600b546001600160a01b031693505f925082915081905080610d9d565b9450806001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610c12575060408051601f3d908101601f19168201909252610c0f9181019061234a565b60015b610c32575050600b546001600160a01b031693505f915081905080610d9d565b9350806001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610c8e575060408051601f3d908101601f19168201909252610c8b9181019061234a565b60015b610cab575050600b546001600160a01b031693505f905080610d9d565b92505f6001600160a01b038616301480610ccd57506001600160a01b03851630145b8015610d4557507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316866001600160a01b03161480610d4557507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316856001600160a01b0316145b90505f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316856001600160a01b0316149050818015610d895750805b600b546001600160a01b0316985093505050505b9091929394565b600a546001600160a01b03163314610dce5760405162461bcd60e51b815260040161071790612324565b600d5460ff1615610e215760405162461bcd60e51b815260206004820152601760248201527f54726164696e6720616c726561647920656e61626c65640000000000000000006044820152606401610717565b600d805460ff191660011790556040517fb3da2db3dfc3778f99852546c6e9ab39ec253f9de7b0847afec61bd27878e92390610e609042815260200190565b60405180910390a1565b5f5f5f5a905060095461c350610e809190612379565b9150818110159250909192565b60018054610658906122ec565b5f6106e33384846113d8565b600a546001600160a01b03163314610ed05760405162461bcd60e51b815260040161071790612324565b600a8211158015610ee25750600a8111155b610f1d5760405162461bcd60e51b815260206004820152600c60248201526b0a8c2f040e8dede40d0d2ced60a31b6044820152606401610717565b600591909155600655565b600a546001600160a01b03163314610f525760405162461bcd60e51b815260040161071790612324565b6001600160a01b03919091165f908152600c60205260409020805460ff1916911515919091179055565b600a546001600160a01b03163314610fa65760405162461bcd60e51b815260040161071790612324565b6103e8600254610fb6919061238c565b811115610ffc5760405162461bcd60e51b815260206004820152601460248201527309ad2dc40c4c2d8c2dcc6ca40e8dede40d0d2ced60631b6044820152606401610717565b60078190556040518181527f4e1cd0a17dbc393262d4d9b66380671f5273c5f0a34fed0ed36c50ba6b1f0e16906020016107e0565b600a546001600160a01b0316331461105b5760405162461bcd60e51b815260040161071790612324565b5f60078190556040519081527f4e1cd0a17dbc393262d4d9b66380671f5273c5f0a34fed0ed36c50ba6b1f0e1690602001610e60565b3330146110cc5760405162461bcd60e51b815260206004820152600960248201526827b7363c9039b2b63360b91b6044820152606401610717565b4281101561110f5760405162461bcd60e51b815260206004820152601060248201526f111958591b1a5b9948195e1c1a5c995960821b6044820152606401610717565b60095460408051600481526024810182526020810180516001600160e01b0316634348b59b60e01b17905290515f9283926001600160a01b0387169261115591906123ab565b5f604051808303815f8787f1925050503d805f811461118f576040519150601f19603f3d011682016040523d82523d5f602084013e611194565b606091505b5091509150816111a382611ca8565b906111c15760405162461bcd60e51b8152600401610717919061219b565b5050505050565b600a546001600160a01b031633146111f25760405162461bcd60e51b815260040161071790612324565b600a80546001600160a01b0319169055565b600a546001600160a01b0316331461122e5760405162461bcd60e51b815260040161071790612324565b60085460ff16156112735760405162461bcd60e51b815260206004820152600f60248201526e0416c726561647920696e207377617608c1b6044820152606401610717565b305f908152600360205260409020546112c25760405162461bcd60e51b815260206004820152601160248201527004e6f20746f6b656e7320746f207377617607c1b6044820152606401610717565b6112ca611d07565b565b6001600160a01b0383166113225760405162461bcd60e51b815260206004820152601960248201527f417070726f76652066726f6d207a65726f2061646472657373000000000000006044820152606401610717565b6001600160a01b0382166113785760405162461bcd60e51b815260206004820152601760248201527f417070726f766520746f207a65726f20616464726573730000000000000000006044820152606401610717565b6001600160a01b038381165f8181526004602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b03831661142e5760405162461bcd60e51b815260206004820152601a60248201527f5472616e736665722066726f6d207a65726f20616464726573730000000000006044820152606401610717565b6001600160a01b0382166114845760405162461bcd60e51b815260206004820152601860248201527f5472616e7366657220746f207a65726f206164647265737300000000000000006044820152606401610717565b6001600160a01b0383165f908152600360205260409020548111156114e25760405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b6044820152606401610717565b600d5460ff168061150a57506001600160a01b0383165f908152600c602052604090205460ff165b8061152c57506001600160a01b0382165f908152600c602052604090205460ff165b6115785760405162461bcd60e51b815260206004820152601760248201527f54726164696e67206e6f7420656e61626c6564207965740000000000000000006044820152606401610717565b305f908152600360205260409020546007548110801590819061159e575060085460ff16155b80156115b85750600b546001600160a01b03868116911614155b156115c5576115c5611d07565b6001600160a01b0385165f908152600c602052604090205460019060ff168061160557506001600160a01b0385165f908152600c602052604090205460ff165b1561160d57505f5b60085460ff161561161b57505f5b5f811561172357600b546001600160a01b0390811688821681149188161481156116605760646005548861164f91906123c1565b611659919061238c565b9250611683565b80156116835760646006548861167691906123c1565b611680919061238c565b92505b821561172057305f90815260036020526040812080548592906116a7908490612379565b909155505060405183815230906001600160a01b038b16907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a36040518381527f092c6768ba45dfdc937f94a27a0c5be8334952f1558bc7dd41b3e8707502e1b69060200160405180910390a15b50505b5f61172e82876123d8565b6001600160a01b0389165f9081526003602052604081208054929350889290919061175a9084906123d8565b90915550506001600160a01b0387165f9081526003602052604081208054839290611786908490612379565b92505081905550866001600160a01b0316886001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516117d291815260200190565b60405180910390a35050505050505050565b5f8190505f5f826001600160a01b0316630dfe16816040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611844575060408051601f3d908101601f191682019092526118419181019061234a565b60015b6118905760405162461bcd60e51b815260206004820181905260248201527f496e76616c696420706169723a20746f6b656e302063616c6c206661696c65646044820152606401610717565b9150826001600160a01b031663d21220a76040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156118ec575060408051601f3d908101601f191682019092526118e99181019061234a565b60015b6119385760405162461bcd60e51b815260206004820181905260248201527f496e76616c696420706169723a20746f6b656e312063616c6c206661696c65646044820152606401610717565b90506001600160a01b03821630148061195957506001600160a01b03811630145b6119a55760405162461bcd60e51b815260206004820181905260248201527f5061697220646f6573206e6f7420636f6e7461696e207468697320746f6b656e6044820152606401610717565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161480611a1657507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b0316145b611a625760405162461bcd60e51b815260206004820152601a60248201527f5061697220646f6573206e6f7420636f6e7461696e20574554480000000000006044820152606401610717565b60405163e6a4390560e01b81523060048201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660248301525f917f00000000000000000000000000000000000000000000000000000000000000009091169063e6a4390590604401602060405180830381865afa158015611af0573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b14919061234a565b9050846001600160a01b0316816001600160a01b031614611b775760405162461bcd60e51b815260206004820152601e60248201527f50616972206e6f74207265676973746572656420696e20666163746f727900006044820152606401610717565b836001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611bd1575060408051601f3d908101601f19168201909252611bce9181019061234a565b60015b611c275760405162461bcd60e51b815260206004820152602160248201527f496e76616c696420706169723a20666163746f72792063616c6c206661696c656044820152601960fa1b6064820152608401610717565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b031614611ca05760405162461bcd60e51b81526020600482015260156024820152740a0c2d2e440ccc2c6e8dee4f240dad2e6dac2e8c6d605b1b6044820152606401610717565b505050505050565b6060604482511015611ced57505060408051808201909152601d81527f5472616e73616374696f6e2072657665727465642073696c656e746c79000000602082015290565b600482019150818060200190518101906106e7919061242c565b6002600e5403611d595760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610717565b6002600e55305f9081526003602052604081205490819003611d7b5750612166565b6008805460ff191660011790555f5a90505f6064600254611d9c919061238c565b905080831115611daa578092505b305f9081526003602052604081208054859290611dc89084906123d8565b9091555050600a546001600160a01b03165f9081526003602052604081208054859290611df6908490612379565b9091555050600a546040518481526001600160a01b039091169030907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a3478015611f5757600a546040515f916001600160a01b03169083908381818185875af1925050503d805f8114611e90576040519150601f19603f3d011682016040523d82523d5f602084013e611e95565b606091505b5050905080611f5557600a54604080518481526001600160a01b0390921660208301527f0d4cd95169a26aee182a4ccf703957332b0124f339d2df71fca46b9860152702910160405180910390a17f1ee26af29c98a78de89a0efdcde8c7e768e077383fe7189c5e1f52ff58282fbd5a604051611f4c91906040808252601e908201527f455448207472616e7366657220746f206d616e61676572206661696c656400006060820152602081019190915260800190565b60405180910390a15b505b5f611f644261012c612379565b600954600a5460405163f1a8c48360e01b81526001600160a01b03909116600482015260248101839052919250309163f1a8c48391906044015f604051808303815f88803b158015611fb4575f5ffd5b5087f193505050508015611fc6575060015b61210457611fd26124c4565b806308c379a0036120745750611fe66124dd565b80611ff15750612076565b5f5a90507f1ee26af29c98a78de89a0efdcde8c7e768e077383fe7189c5e1f52ff58282fbd8282604051612026929190612561565b60405180910390a1604080518881525f602082018190528183015290517f6321922449d3b78d6e111db6ff7fa0b0963798d0b026d2d90df032a1706f5f069181900360600190a15050612156565b505b3d80801561209f576040519150601f19603f3d011682016040523d82523d5f602084013e6120a4565b606091505b505f5a90507f1ee26af29c98a78de89a0efdcde8c7e768e077383fe7189c5e1f52ff58282fbd8160405161202691906040808252600f908201526e2637bb96b632bb32b61032b93937b960891b6060820152602081019190915260800190565b5f5a61211090866123d8565b60408051888152600160208201529081018290529091507f6321922449d3b78d6e111db6ff7fa0b0963798d0b026d2d90df032a1706f5f069060600160405180910390a1505b50506008805460ff191690555050505b6001600e55565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6121ad602083018461216d565b9392505050565b6001600160a01b03811681146121c8575f5ffd5b50565b5f5f604083850312156121dc575f5ffd5b82356121e7816121b4565b946020939093013593505050565b5f60208284031215612205575f5ffd5b5035919050565b5f5f5f6060848603121561221e575f5ffd5b8335612229816121b4565b92506020840135612239816121b4565b929592945050506040919091013590565b5f5f6040838503121561225b575f5ffd5b8235612266816121b4565b91506020830135612276816121b4565b809150509250929050565b5f60208284031215612291575f5ffd5b81356121ad816121b4565b5f5f604083850312156122ad575f5ffd5b50508035926020909101359150565b5f5f604083850312156122cd575f5ffd5b82356122d8816121b4565b915060208301358015158114612276575f5ffd5b600181811c9082168061230057607f821691505b60208210810361231e57634e487b7160e01b5f52602260045260245ffd5b50919050565b6020808252600c908201526b27b7363c9036b0b730b3b2b960a11b604082015260600190565b5f6020828403121561235a575f5ffd5b81516121ad816121b4565b634e487b7160e01b5f52601160045260245ffd5b808201808211156106e7576106e7612365565b5f826123a657634e487b7160e01b5f52601260045260245ffd5b500490565b5f82518060208501845e5f920191825250919050565b80820281158282048414176106e7576106e7612365565b818103818111156106e7576106e7612365565b634e487b7160e01b5f52604160045260245ffd5b601f8201601f1916810167ffffffffffffffff81118282101715612425576124256123eb565b6040525050565b5f6020828403121561243c575f5ffd5b815167ffffffffffffffff811115612452575f5ffd5b8201601f81018413612462575f5ffd5b805167ffffffffffffffff81111561247c5761247c6123eb565b604051612493601f8301601f1916602001826123ff565b8181528560208385010111156124a7575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60033d11156124da5760045f5f3e505f5160e01c5b90565b5f60443d10156124ea5790565b6040513d600319016004823e80513d602482011167ffffffffffffffff8211171561251457505090565b808201805167ffffffffffffffff811115612530575050505090565b3d840160031901828201602001111561254a575050505090565b612559602082850101856123ff565b509392505050565b604081525f612573604083018561216d565b9050826020830152939250505056fea264697066735822122025e6d122f521a71de120ea70a004ea7ffb4ed98d44ebd97b85a1a05719b72c1164736f6c634300081e0033a264697066735822122010f2865de0f6782edb245490d66edae32c770da3020381ccacc144950c99d06864736f6c634300081e0033

Verified Source Code Full Match

Compiler: v0.8.30+commit.73712a01 EVM: prague Optimization: Yes (200 runs)
BuyBackManagerFixed.sol 562 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;


import "./Token.sol";
/**
 * @title Manager
 */

interface IERC20 {
    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address recipient, uint256 amount) external returns (bool);
    function allowance(address owner, address spender) external view returns (uint256);
    function approve(address spender, uint256 amount) external returns (bool);
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
}

interface IUniswapV2Router02 {
    function factory() external pure returns (address);
    function WETH() external pure returns (address);
    
    function addLiquidityETH(
        address token,
        uint amountTokenDesired,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external payable returns (uint amountToken, uint amountETH, uint liquidity);
    
    function removeLiquidityETH(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external returns (uint amountToken, uint amountETH);
    
    function swapExactETHForTokensSupportingFeeOnTransferTokens(
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external payable;
    
    function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
}

interface IBuybackToken {
    function initialize(address _pair, address _buybackManager) external;
}


contract BuybackManagerFixed {
    
    // State variables
    address public owner;
    address public tokenAddress;
    address public pairAddress;
    IUniswapV2Router02 public router;
    
    // Validated swap path
    address[] public swapPath;
    
    bool public isInitialized;
    bool private locked;
    
    // Security settings
    uint256 public slippageTolerance = 10;
    uint256 public constant MAX_RETRIES = 2;
    uint256 public slippageIncreasePerRetry = 5;
    
    // Deadline configuration
    uint256 public defaultDeadlineSeconds = 60;
    
    // Gas management
    uint256 public minGasReserve = 200000;
    uint256 public buybackGasLimit = 300000;
    
    // Events
    event TokenDeployed(address indexed tokenAddress, address indexed pair);
    event LiquidityAdded(uint256 tokenAmount, uint256 ethAmount, uint256 lpTokens);
    event BuybackExecuted(
        uint256 ethAmount, 
        uint256 tokensBought, 
        uint256 gasUsed, 
        uint256 attemptNumber,
        uint256 minAmountOut,
        uint256 deadline
    );
    event TokensBurned(uint256 amount);
    event LPTokensBurned(uint256 amount);
    event LPTokensWithdrawn(uint256 amount, address indexed to);
    event SlippageToleranceUpdated(uint256 newTolerance);
    event DeadlineUpdated(uint256 newDeadline);
    event GasSettingsUpdated(uint256 minReserve, uint256 gasLimit);
    event InsufficientGasForBuyback(uint256 available, uint256 required);
    event EmergencyETHRecovered(uint256 amount, address indexed to);
    event BuybackRetryAttempt(uint256 attemptNumber, uint256 ethBalance, uint256 appliedSlippage, uint256 minAmountOut);
    event BuybackFailedAllRetries(uint256 finalEthBalance, uint256 totalAttempts);
    event RetryConfigUpdated(uint256 slippageIncrease);
    event SwapPathValidated(address weth, address token);
    
    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;
    }
    
    modifier onlyToken() {
        require(msg.sender == tokenAddress, "Only token can call");
        require(tokenAddress != address(0), "Token not initialized");
        _;
    }
    
    modifier nonReentrant() {
        require(!locked, "Reentrancy detected");
        locked = true;
        _;
        locked = false;
    }
    
    constructor(address _router) {
        require(_router != address(0), "Invalid router");
        owner = msg.sender;
        router = IUniswapV2Router02(_router);
        
        // Validate WETH
        address weth = router.WETH();
        require(weth != address(0), "Invalid WETH address");
        
        // Initialize path (token will be set during deployment)
        swapPath = new address[](2);
        swapPath[0] = weth;
    }
    
    /**
     * @dev Get fresh LP token balance (no manual tracking)
     */
    function _getLPBalance() internal view returns (uint256) {
        if (pairAddress == address(0)) return 0;
        return IERC20(pairAddress).balanceOf(address(this));
    }
    
    /**
     * @dev Calculate minAmountOut with explicit slippage
     */
    function _calculateMinAmountOut(uint256 ethAmount, uint256 slippage) internal view returns (uint256) {
        require(slippage <= 50, "Slippage too high");
        
        uint256[] memory amountsOut = router.getAmountsOut(ethAmount, swapPath);
        uint256 expectedTokens = amountsOut[1];
        uint256 minTokens = expectedTokens * (100 - slippage) / 100;
        
        require(minTokens > 0, "Min tokens too low");
        return minTokens;
    }
    
    /**
     * ✅ FIX #1 & #2: Deploy token directly with correct parameters
     * This is a placeholder - in actual implementation, you need to either:
     * 1. Import BuybackTokenSecured and use: new BuybackTokenSecured(...)
     * 2. Use a factory pattern
     * 
     * For this example, we'll show the CREATE2 approach with proper parameters
     */
    function deployTokenAndAddLiquidity(
        string memory name,
        string memory symbol,
        uint256 totalSupply,
        uint256 tokensForLP,
        bytes32 salt  // Optional: for CREATE2 deterministic deployment
    ) external payable onlyOwner nonReentrant {
        require(!isInitialized, "Already initialized");
        require(msg.value > 0, "Need ETH for liquidity");
        require(tokensForLP <= totalSupply, "LP tokens exceed supply");
        require(tokensForLP > 0, "LP tokens must be > 0");
        
        // ✅ FIX #1: Deploy token directly (not from arbitrary bytecode)
        // Get the bytecode of BuybackTokenSecured
        bytes memory bytecode = type(BuybackTokenSecured).creationCode;
        
        // ✅ FIX #2: Encode ALL required constructor parameters
        bytes memory constructorArgs = abi.encode(
            name,
            symbol,
            totalSupply,
            address(this),      // buyback manager
            router.WETH(),      // ✅ WETH address
            router.factory()    // ✅ Factory address
        );
        
        bytes memory deploymentData = abi.encodePacked(bytecode, constructorArgs);
        
        address deployedToken;
        
        // Deploy with CREATE2 for deterministic address
        assembly {
            deployedToken := create2(
                0,
                add(deploymentData, 0x20),
                mload(deploymentData),
                salt
            )
            
            if iszero(extcodesize(deployedToken)) {
                revert(0, 0)
            }
        }
        
        require(deployedToken != address(0), "Token deployment failed");
        tokenAddress = deployedToken;
        
        // Complete and validate swap path
        swapPath[1] = tokenAddress;
        require(swapPath[0] != address(0), "Invalid WETH in path");
        require(swapPath[1] == tokenAddress, "Invalid token in path");
        
        emit SwapPathValidated(swapPath[0], swapPath[1]);
        
        // Approve router
        require(
            IERC20(tokenAddress).approve(address(router), tokensForLP),
            "Approval failed"
        );
        
        (uint256 amountToken, uint256 amountETH, uint256 liquidity) = router.addLiquidityETH{value: msg.value}(
            tokenAddress,
            tokensForLP,
            tokensForLP * 95 / 100,
            msg.value * 95 / 100,
            address(this),
            block.timestamp + defaultDeadlineSeconds
        );
        
        require(amountToken > 0 && amountETH > 0, "Liquidity add failed");
        require(liquidity > 0, "No LP tokens received");
        
        pairAddress = IUniswapV2Factory(router.factory()).getPair(
            tokenAddress,
            router.WETH()
        );
        require(pairAddress != address(0), "Pair creation failed");
        
        // Initialize the token with correct pair address
        IBuybackToken(tokenAddress).initialize(pairAddress, address(this));
        
        isInitialized = true;
        
        emit TokenDeployed(tokenAddress, pairAddress);
        emit LiquidityAdded(amountToken, amountETH, liquidity);
    }
    
    /**
     * @dev Execute buyback and burn - called by token contract
     */
    function executeBuybackAndBurn() external onlyToken nonReentrant {
        uint256 ethBalance = address(this).balance;
        
        if (ethBalance == 0) return;
        
        uint256 gasStart = gasleft();
        
        // Check gas availability
        if (gasStart < buybackGasLimit + minGasReserve) {
            emit InsufficientGasForBuyback(gasStart, buybackGasLimit + minGasReserve);
            return;
        }
        
        // Progressive retry logic with increasing slippage
        for (uint256 attempt = 0; attempt <= MAX_RETRIES; attempt++) {
            
            // Fresh balance check on each iteration
            ethBalance = address(this).balance;
            if (ethBalance == 0) return;
            
            // Progressive slippage
            uint256 currentSlippage = slippageTolerance + (attempt * slippageIncreasePerRetry);
            if (currentSlippage > 50) currentSlippage = 50;
            
            // Calculate minimum amount for this attempt
            uint256 minAmountOut = _calculateMinAmountOut(ethBalance, currentSlippage);
            
            // Calculate deadline for this swap
            uint256 deadline = block.timestamp + defaultDeadlineSeconds;
            
            emit BuybackRetryAttempt(attempt + 1, ethBalance, currentSlippage, minAmountOut);
            
            // Get token balance before swap
            uint256 tokenBalanceBefore = IERC20(tokenAddress).balanceOf(address(this));
            
            try router.swapExactETHForTokensSupportingFeeOnTransferTokens{value: ethBalance}(
                minAmountOut,
                swapPath,
                address(this),
                deadline
            ) {
                // Get actual tokens received
                uint256 tokenBalanceAfter = IERC20(tokenAddress).balanceOf(address(this));
                uint256 tokensBought = tokenBalanceAfter - tokenBalanceBefore;
                
                // Validate we got at least minimum
                require(tokensBought >= minAmountOut, "Slippage too high");
                
                if (tokensBought > 0) {
                    // Burn tokens by sending to dead address
                    address deadAddress = 0x000000000000000000000000000000000000dEaD;
                    require(
                        IERC20(tokenAddress).transfer(deadAddress, tokensBought),
                        "Burn transfer failed"
                    );
                    
                    uint256 gasUsed = gasStart - gasleft();
                    emit BuybackExecuted(ethBalance, tokensBought, gasUsed, attempt + 1, minAmountOut, deadline);
                    emit TokensBurned(tokensBought);
                }
                return;
                
            } catch Error(string memory reason) {
                // If not last attempt, continue to next iteration
                if (attempt < MAX_RETRIES) {
                    continue;
                }
                
                // All retries failed
                emit BuybackFailedAllRetries(ethBalance, attempt + 1);
                return;
                
            } catch (bytes memory) {
                // Low-level error
                if (attempt < MAX_RETRIES) {
                    continue;
                }
                
                emit BuybackFailedAllRetries(ethBalance, attempt + 1);
                return;
            }
        }
    }
    
    /**
     * @dev Manual retry with explicit parameters
     */
    function retryBuyback(
        uint256 minAmountOut,
        uint256 customDeadlineSeconds
    ) external onlyOwner nonReentrant {
        require(minAmountOut > 0, "Invalid minAmountOut");
        require(customDeadlineSeconds >= 15 && customDeadlineSeconds <= 600, "Invalid deadline");
        
        uint256 ethBalance = address(this).balance;
        require(ethBalance > 0, "No ETH for buyback");
        
        uint256 gasStart = gasleft();
        require(gasStart >= buybackGasLimit, "Insufficient gas provided");
        
        // Retry loop with explicit parameters
        for (uint256 attempt = 0; attempt <= MAX_RETRIES; attempt++) {
            
            // Fresh balance check
            ethBalance = address(this).balance;
            if (ethBalance == 0) return;
            
            // Progressive slippage
            uint256 currentSlippage = slippageTolerance + (attempt * slippageIncreasePerRetry);
            if (currentSlippage > 50) currentSlippage = 50;
            
            // Calculate min amount for this attempt (or use provided)
            uint256 attemptMinAmount = (attempt == 0) ? minAmountOut : _calculateMinAmountOut(ethBalance, currentSlippage);
            
            // Explicit deadline for this attempt
            uint256 deadline = block.timestamp + customDeadlineSeconds;
            
            uint256 tokenBalanceBefore = IERC20(tokenAddress).balanceOf(address(this));
            
            try router.swapExactETHForTokensSupportingFeeOnTransferTokens{value: ethBalance}(
                attemptMinAmount,
                swapPath,
                address(this),
                deadline
            ) {
                uint256 tokenBalanceAfter = IERC20(tokenAddress).balanceOf(address(this));
                uint256 tokensBought = tokenBalanceAfter - tokenBalanceBefore;
                
                // Validate output
                require(tokensBought >= attemptMinAmount, "Slippage too high");
                
                if (tokensBought > 0) {
                    address deadAddress = 0x000000000000000000000000000000000000dEaD;
                    IERC20(tokenAddress).transfer(deadAddress, tokensBought);
                    
                    emit BuybackExecuted(ethBalance, tokensBought, gasStart - gasleft(), attempt + 1, attemptMinAmount, deadline);
                    emit TokensBurned(tokensBought);
                }
                return;
                
            } catch {
                emit BuybackRetryAttempt(attempt + 1, ethBalance, currentSlippage, attemptMinAmount);
                
                if (attempt == MAX_RETRIES) {
                    emit BuybackFailedAllRetries(ethBalance, attempt + 1);
                    revert("Manual retry failed after all attempts");
                }
            }
        }
    }
    
    /**
     * @dev Withdraw LP tokens with fresh balance
     */
    function withdrawLPTokens(uint256 amount) external onlyOwner nonReentrant {
        require(pairAddress != address(0), "No pair");
        require(amount > 0, "Amount must be > 0");
        
        uint256 actualBalance = _getLPBalance();
        require(actualBalance >= amount, "Insufficient LP balance");
        
        require(
            IERC20(pairAddress).transfer(owner, amount),
            "LP transfer failed"
        );
        
        emit LPTokensWithdrawn(amount, owner);
    }
    
    function withdrawAllLPTokens() external onlyOwner nonReentrant {
        require(pairAddress != address(0), "No pair");
        
        uint256 balance = _getLPBalance();
        require(balance > 0, "No LP tokens");
        
        require(
            IERC20(pairAddress).transfer(owner, balance),
            "LP transfer failed"
        );
        
        emit LPTokensWithdrawn(balance, owner);
    }
    
    function removeLiquidity(
        uint256 lpAmount,
        uint256 minToken,
        uint256 minETH
    ) external onlyOwner nonReentrant returns (uint256 amountToken, uint256 amountETH) {
        require(pairAddress != address(0), "No pair");
        require(lpAmount > 0, "Amount must be > 0");
        
        uint256 actualBalance = _getLPBalance();
        require(actualBalance >= lpAmount, "Insufficient LP balance");
        
        require(
            IERC20(pairAddress).approve(address(router), lpAmount),
            "LP approval failed"
        );
        
        (amountToken, amountETH) = router.removeLiquidityETH(
            tokenAddress,
            lpAmount,
            minToken,
            minETH,
            owner,
            block.timestamp + defaultDeadlineSeconds
        );
        
        emit LiquidityAdded(amountToken, amountETH, lpAmount);
    }
    
    function burnLPTokens(uint256 amount) external onlyOwner nonReentrant {
        require(pairAddress != address(0), "No pair");
        require(amount > 0, "Amount must be > 0");
        
        uint256 actualBalance = _getLPBalance();
        require(actualBalance >= amount, "Insufficient LP balance");
        
        address deadAddress = 0x000000000000000000000000000000000000dEaD;
        
        require(
            IERC20(pairAddress).transfer(deadAddress, amount),
            "Burn failed"
        );
        
        emit LPTokensBurned(amount);
    }
    
    function updateSlippageTolerance(uint256 _tolerance) external onlyOwner {
        require(_tolerance <= 50, "Tolerance too high");
        slippageTolerance = _tolerance;
        emit SlippageToleranceUpdated(_tolerance);
    }
    
    function updateDeadline(uint256 _seconds) external onlyOwner {
        require(_seconds >= 15, "Deadline too short");
        require(_seconds <= 600, "Deadline too long");
        defaultDeadlineSeconds = _seconds;
        emit DeadlineUpdated(_seconds);
    }
    
    function updateRetryConfig(uint256 _slippageIncrease) external onlyOwner {
        require(_slippageIncrease >= 1 && _slippageIncrease <= 10, "Invalid slippage increase");
        slippageIncreasePerRetry = _slippageIncrease;
        emit RetryConfigUpdated(_slippageIncrease);
    }
    
    function updateGasSettings(uint256 _minReserve, uint256 _gasLimit) external onlyOwner {
        require(_minReserve >= 50000, "Reserve too low");
        require(_gasLimit >= 200000, "Gas limit too low");
        require(_gasLimit <= 500000, "Gas limit too high");
        
        minGasReserve = _minReserve;
        buybackGasLimit = _gasLimit;
        
        emit GasSettingsUpdated(_minReserve, _gasLimit);
    }
    
    function estimateBuybackGas() external view returns (uint256 estimatedGas, bool hasEnoughGas) {
        estimatedGas = buybackGasLimit;
        hasEnoughGas = gasleft() >= estimatedGas;
        return (estimatedGas, hasEnoughGas);
    }
    
    /**
     * ✅ FIX #3: Improved ETH recovery using call instead of transfer
     */
    function emergencyRecoverETH() external onlyOwner nonReentrant {
        uint256 balance = address(this).balance;
        require(balance > 0, "No ETH to recover");
        
        // ✅ Use call for better compatibility
        (bool success, ) = payable(owner).call{value: balance}("");
        require(success, "ETH transfer failed");
        
        emit EmergencyETHRecovered(balance, owner);
    }
    
    receive() external payable {}
    
    function renounceOwnership() external onlyOwner {
        owner = address(0);
    }
    
    function transferOwnership(address newOwner) external onlyOwner {
        require(newOwner != address(0), "Invalid address");
        owner = newOwner;
    }
    
    function getCurrentLPBalance() external view returns (uint256) {
        return _getLPBalance();
    }
    
    function getRetryConfig() external view returns (
        uint256 currentMaxRetries,
        uint256 currentSlippageIncrease,
        uint256 baseSlippage
    ) {
        return (MAX_RETRIES, slippageIncreasePerRetry, slippageTolerance);
    }
    
    function getSwapPath() external view returns (address[] memory) {
        return swapPath;
    }
}
Token.sol 489 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/**
 * @title Token
 */

interface IUniswapV2Pair {
    function token0() external view returns (address);
    function token1() external view returns (address);
    function factory() external view returns (address);
}

interface IUniswapV2Factory {
    function getPair(address tokenA, address tokenB) external view returns (address);
}

contract BuybackTokenSecured {
    
    // Token details
    string public name;
    string public symbol;
    uint8 public constant decimals = 18;
    uint256 public totalSupply;
    
    // Balances and allowances
    mapping(address => uint256) private _balances;
    mapping(address => mapping(address => uint256)) private _allowances;
    
    // Tax configuration
    uint256 public buyTax = 4;
    uint256 public sellTax = 4;
    uint256 private constant TAX_DENOMINATOR = 100;
    
    // Buyback configuration
    uint256 public minBalanceForBuyback;
    bool private inSwap;
    
    // Gas management for buyback calls
    uint256 public buybackGasLimit = 550000;
    
    // Addresses
    address public buybackManager;
    address public pairAddress;
    address public immutable WETH;
    address public immutable factory;
    address private immutable deployer;
    
    // Exclusions
    mapping(address => bool) public isExcludedFromFee;
    
    // Trading control
    bool public tradingEnabled;
    
    // Reentrancy guard
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;
    uint256 private _status;
    
    // Events
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
    event TradingEnabled(uint256 timestamp);
    event BuybackTriggered(uint256 tokensSwapped, bool success, uint256 gasUsed);
    event TaxCollected(uint256 amount);
    event BuybackGasLimitUpdated(uint256 newLimit);
    event BuybackFailed(string reason, uint256 gasLeft);
    event MinBalanceUpdated(uint256 newMinBalance);
    event PairValidated(address indexed pair, address token0, address token1);
    event ETHTransferFailed(uint256 amount, address recipient);
    
    // Modifiers
    modifier onlyManager() {
        require(msg.sender == buybackManager, "Only manager");
        _;
    }
    
    modifier nonReentrant() {
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
        _status = _ENTERED;
        _;
        _status = _NOT_ENTERED;
    }
    
    constructor(
        string memory _name,
        string memory _symbol,
        uint256 _totalSupply,
        address _buybackManager,
        address _weth,
        address _factory
    ) {
        require(_buybackManager != address(0), "Invalid manager");
        require(_weth != address(0), "Invalid WETH");
        require(_factory != address(0), "Invalid factory");
        
        name = _name;
        symbol = _symbol;
        totalSupply = _totalSupply;
        buybackManager = _buybackManager;
        deployer = msg.sender; 
        WETH = _weth;
        factory = _factory;
        
        // Set minimal threshold (0.01% of supply)
        minBalanceForBuyback = _totalSupply / 10000;
        
        // Initialize reentrancy guard
        _status = _NOT_ENTERED;
        
        // Mint entire supply to buyback manager
        _balances[_buybackManager] = _totalSupply;
        
        // Exclude manager and token contract from fees
        isExcludedFromFee[_buybackManager] = true;
        isExcludedFromFee[address(this)] = true;
        
        emit Transfer(address(0), _buybackManager, _totalSupply);
    }
    
    /**
     * @dev Validate pair address during initialization
     */
    function initialize(address _pair, address _manager) external {
        require(msg.sender == buybackManager, "Only manager");
        require(pairAddress == address(0), "Already initialized");
        require(_pair != address(0), "Invalid pair address");
        require(_manager != address(0), "Invalid manager address");
        
        // Validate that _pair is a real Uniswap pair
        _validatePairAddress(_pair);
        
        pairAddress = _pair;
        buybackManager = _manager;
        isExcludedFromFee[_pair] = false;
    }
    
    /**
     * @dev Validate pair is legitimate Uniswap pair
     */
    function _validatePairAddress(address _pair) internal view {
        IUniswapV2Pair pair = IUniswapV2Pair(_pair);
        
        // Get tokens from pair
        address token0;
        address token1;
        
        try pair.token0() returns (address _token0) {
            token0 = _token0;
        } catch {
            revert("Invalid pair: token0 call failed");
        }
        
        try pair.token1() returns (address _token1) {
            token1 = _token1;
        } catch {
            revert("Invalid pair: token1 call failed");
        }
        
        // Verify one of the tokens is this token
        require(
            token0 == address(this) || token1 == address(this),
            "Pair does not contain this token"
        );
        
        // Verify the other token is WETH
        require(
            token0 == WETH || token1 == WETH,
            "Pair does not contain WETH"
        );
        
        // Verify pair exists in factory
        address expectedPair = IUniswapV2Factory(factory).getPair(address(this), WETH);
        require(expectedPair == _pair, "Pair not registered in factory");
        
        // Verify pair's factory matches
        try pair.factory() returns (address pairFactory) {
            require(pairFactory == factory, "Pair factory mismatch");
        } catch {
            revert("Invalid pair: factory call failed");
        }
        
        // emit PairValidated(_pair, token0, token1);
    }
    
    function enableTrading() external onlyManager {
        require(!tradingEnabled, "Trading already enabled");
        tradingEnabled = true;
        emit TradingEnabled(block.timestamp);
    }
    
    function balanceOf(address account) public view returns (uint256) {
        return _balances[account];
    }
    
    function transfer(address recipient, uint256 amount) public returns (bool) {
        _transfer(msg.sender, recipient, amount);
        return true;
    }
    
    function allowance(address owner, address spender) public view returns (uint256) {
        return _allowances[owner][spender];
    }
    
    function approve(address spender, uint256 amount) public returns (bool) {
        _approve(msg.sender, spender, amount);
        return true;
    }
    
    function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
        _transfer(sender, recipient, amount);
        
        uint256 currentAllowance = _allowances[sender][msg.sender];
        require(currentAllowance >= amount, "Transfer amount exceeds allowance");
        unchecked {
            _approve(sender, msg.sender, currentAllowance - amount);
        }
        
        return true;
    }
    
    /**
     * ✅ FIX #1: Added trading enabled check
     */
    function _transfer(address sender, address recipient, uint256 amount) internal {
        require(sender != address(0), "Transfer from zero address");
        require(recipient != address(0), "Transfer to zero address");
        require(_balances[sender] >= amount, "Insufficient balance");
        
        // ✅ FIX #1: CHECK TRADING ENABLED
        // Allow transfers if:
        // 1. Trading is enabled, OR
        // 2. Sender is excluded (manager, token contract), OR
        // 3. Recipient is excluded
        require(
            tradingEnabled || 
            isExcludedFromFee[sender] || 
            isExcludedFromFee[recipient],
            "Trading not enabled yet"
        );
        
        // Check if we should trigger buyback
        uint256 contractTokenBalance = _balances[address(this)];
        bool canSwap = contractTokenBalance >= minBalanceForBuyback;
        
        if (canSwap && !inSwap && sender != pairAddress) {
            _triggerBuyback();
        }
        
        // Determine if we should take tax
        bool takeFee = true;
        
        if (isExcludedFromFee[sender] || isExcludedFromFee[recipient]) {
            takeFee = false;
        }
        
        if (inSwap) {
            takeFee = false;
        }
        
        // Calculate tax amount
        uint256 taxAmount = 0;
        
        if (takeFee) {
            bool isBuy = sender == pairAddress;
            bool isSell = recipient == pairAddress;
            
            if (isBuy) {
                taxAmount = (amount * buyTax) / TAX_DENOMINATOR;
            } else if (isSell) {
                taxAmount = (amount * sellTax) / TAX_DENOMINATOR;
            }
            
            if (taxAmount > 0) {
                _balances[address(this)] += taxAmount;
                emit Transfer(sender, address(this), taxAmount);
                emit TaxCollected(taxAmount);
            }
        }
        
        // Transfer remaining amount
        uint256 amountAfterTax = amount - taxAmount;
        _balances[sender] -= amount;
        _balances[recipient] += amountAfterTax;
        
        emit Transfer(sender, recipient, amountAfterTax);
    }

    function _triggerBuyback() internal nonReentrant {
        uint256 contractTokenBalance = _balances[address(this)];
        
        if (contractTokenBalance == 0) return;
        
        // Set inSwap flag to prevent tax during buyback
        inSwap = true;
        
        uint256 gasBefore = gasleft();
        
        // Cap at 1% of supply per swap
        uint256 maxSwap = totalSupply / 100;
        if (contractTokenBalance > maxSwap) {
            contractTokenBalance = maxSwap;
        }
        
        // Update state BEFORE external calls
        _balances[address(this)] -= contractTokenBalance;
        _balances[buybackManager] += contractTokenBalance;
        emit Transfer(address(this), buybackManager, contractTokenBalance);
        
        uint256 ethBalance = address(this).balance;
        if (ethBalance > 0) {
            (bool ethSent,) = payable(buybackManager).call{value: ethBalance}("");
            if (!ethSent) {
                // Log but don't revert - ETH can be recovered later
                emit ETHTransferFailed(ethBalance, buybackManager);
                emit BuybackFailed("ETH transfer to manager failed", gasleft());
            }
        }
        
        uint256 deadline = block.timestamp + 300; // 5 minute deadline
        
        // Call manager to execute buyback with SUFFICIENT GAS and DEADLINE
        try this.executeBuybackCall{gas: buybackGasLimit}(buybackManager, deadline) {
            uint256 gasUsed = gasBefore - gasleft();
            emit BuybackTriggered(contractTokenBalance, true, gasUsed);
        } catch Error(string memory reason) {
            uint256 gasLeft = gasleft();
            emit BuybackFailed(reason, gasLeft);
            emit BuybackTriggered(contractTokenBalance, false, 0);
        } catch (bytes memory) {
            uint256 gasLeft = gasleft();
            emit BuybackFailed("Low-level error", gasLeft);
            emit BuybackTriggered(contractTokenBalance, false, 0);
        }
        
        // Reset inSwap flag
        inSwap = false;
    }
    
    /**
     * @dev External function with deadline parameter
     */
    function executeBuybackCall(address manager, uint256 deadline) external {
        require(msg.sender == address(this), "Only self");
        require(deadline >= block.timestamp, "Deadline expired");
        
        (bool success, bytes memory returnData) = manager.call{
            gas: buybackGasLimit
        }(
            abi.encodeWithSignature("executeBuybackAndBurn()")
        );
        
        require(success, _getRevertMsg(returnData));
    }
    
    /**
     * @dev Extract revert message from return data
     */
    function _getRevertMsg(bytes memory returnData) internal pure returns (string memory) {
        if (returnData.length < 68) return "Transaction reverted silently";
        
        assembly {
            returnData := add(returnData, 0x04)
        }
        return abi.decode(returnData, (string));
    }
    
    /**
     * @dev Manual trigger buyback - Can be called by manager
     */
    function manualBuyback() external onlyManager {
        require(!inSwap, "Already in swap");
        require(_balances[address(this)] > 0, "No tokens to swap");
        _triggerBuyback();
    }
    
    /**
     * @dev Update gas limit for buyback calls
     */
    function updateBuybackGasLimit(uint256 _gasLimit) external onlyManager {
        require(_gasLimit >= 400000, "Gas limit too low");
        require(_gasLimit <= 1000000, "Gas limit too high");
        buybackGasLimit = _gasLimit;
        emit BuybackGasLimitUpdated(_gasLimit);
    }
    
    /**
     * @dev Update minimal balance threshold for buyback trigger
     */
    function updateMinBalance(uint256 _minBalance) external onlyManager {
        require(_minBalance <= totalSupply / 1000, "Min balance too high");
        minBalanceForBuyback = _minBalance;
        emit MinBalanceUpdated(_minBalance);
    }
    
    /**
     * @dev Disable minimal balance check (trigger on ANY amount)
     */
    function disableMinBalance() external onlyManager {
        minBalanceForBuyback = 0;
        emit MinBalanceUpdated(0);
    }
    
    function _approve(address owner, address spender, uint256 amount) internal {
        require(owner != address(0), "Approve from zero address");
        require(spender != address(0), "Approve to zero address");
        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }
    
    function excludeFromFees(address account, bool excluded) external onlyManager {
        isExcludedFromFee[account] = excluded;
    }
    
    function updateTaxRates(uint256 _buyTax, uint256 _sellTax) external onlyManager {
        require(_buyTax <= 10 && _sellTax <= 10, "Tax too high");
        buyTax = _buyTax;
        sellTax = _sellTax;
    }
    
    function renounceManager() external onlyManager {
        buybackManager = address(0);
    }
    
    /**
     * @dev Check remaining gas and estimate if buyback will succeed
     */
    function estimateGasForBuyback() external view returns (bool sufficient, uint256 required, uint256 available) {
        available = gasleft();
        required = buybackGasLimit + 50000;
        sufficient = available >= required;
    }
    
    /**
     * @dev Get pair validation info
     */
    function getPairInfo() external view returns (
        address pair,
        address token0,
        address token1,
        address pairFactory,
        bool isValid
    ) {
        if (pairAddress == address(0)) {
            return (address(0), address(0), address(0), address(0), false);
        }
        
        IUniswapV2Pair pairContract = IUniswapV2Pair(pairAddress);
        
        try pairContract.token0() returns (address _token0) {
            token0 = _token0;
        } catch {
            return (pairAddress, address(0), address(0), address(0), false);
        }
        
        try pairContract.token1() returns (address _token1) {
            token1 = _token1;
        } catch {
            return (pairAddress, token0, address(0), address(0), false);
        }
        
        try pairContract.factory() returns (address _factory) {
            pairFactory = _factory;
        } catch {
            return (pairAddress, token0, token1, address(0), false);
        }
        
        // Validate
        bool validTokens = (token0 == address(this) || token1 == address(this)) &&
                          (token0 == WETH || token1 == WETH);
        bool validFactory = pairFactory == factory;
        
        isValid = validTokens && validFactory;
        return (pairAddress, token0, token1, pairFactory, isValid);
    }
    
    /**
     * @dev Emergency ETH recovery (if ETH transfer fails during buyback)
     */
    function emergencyRecoverETH() external onlyManager {
        uint256 balance = address(this).balance;
        require(balance > 0, "No ETH to recover");
        
        (bool success, ) = payable(buybackManager).call{value: balance}("");
        require(success, "ETH transfer failed");
    }
    
    receive() external payable {}
}

Read Contract

MAX_RETRIES 0x46ebbdb0 → uint256
buybackGasLimit 0xb7c6b7c8 → uint256
defaultDeadlineSeconds 0x4cdff2fe → uint256
estimateBuybackGas 0x4177b66f → uint256, bool
getCurrentLPBalance 0xccba2ddb → uint256
getRetryConfig 0x1b51fbb1 → uint256, uint256, uint256
getSwapPath 0x8ffb62d2 → address[]
isInitialized 0x392e53cd → bool
minGasReserve 0x9d159568 → uint256
owner 0x8da5cb5b → address
pairAddress 0xa8b08982 → address
router 0xf887ea40 → address
slippageIncreasePerRetry 0x1baaf4bd → uint256
slippageTolerance 0xd03153aa → uint256
swapPath 0x24cc0766 → address
tokenAddress 0x9d76ea58 → address

Write Contract 14 functions

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

burnLPTokens 0x0a0a4189
uint256 amount
deployTokenAndAddLiquidity 0x54f2679a
string name
string symbol
uint256 totalSupply
uint256 tokensForLP
bytes32 salt
emergencyRecoverETH 0x186e2d77
No parameters
executeBuybackAndBurn 0x4348b59b
No parameters
removeLiquidity 0x857620e1
uint256 lpAmount
uint256 minToken
uint256 minETH
returns: uint256, uint256
renounceOwnership 0x715018a6
No parameters
retryBuyback 0xefda182d
uint256 minAmountOut
uint256 customDeadlineSeconds
transferOwnership 0xf2fde38b
address newOwner
updateDeadline 0x42af1884
uint256 _seconds
updateGasSettings 0xc3ef17f3
uint256 _minReserve
uint256 _gasLimit
updateRetryConfig 0x5e3be34d
uint256 _slippageIncrease
updateSlippageTolerance 0x0f9da743
uint256 _tolerance
withdrawAllLPTokens 0x7fcd0e8d
No parameters
withdrawLPTokens 0x452d003f
uint256 amount

Recent Transactions

No transactions found for this address