Cryo Explorer Ethereum Mainnet

Address Contract Verified

Address 0x9d7aeF0cbcD7B5BAe2ccc4cF69F68443468bf9F6
Balance 0 ETH
Nonce 1
Code Size 11818 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

11818 bytes
0x6080604052600436106101fe5760003560e01c806370a082311161011d578063ca15c873116100b0578063dd62ed3e1161007f578063ec571c6a11610064578063ec571c6a1461072d578063ec87621c14610742578063fbac39511461077657600080fd5b8063dd62ed3e1461069b578063df592f7d1461070d57600080fd5b8063ca15c87314610612578063d539139314610632578063d547741f14610666578063d64e53961461068657600080fd5b80639dc29fac116100ec5780639dc29fac1461059d578063a217fddf146105bd578063a9059cbb146105d2578063aef18ae7146105f257600080fd5b806370a08231146104945780639010d07c146104f657806391d148541461051657806395d89b411461058857600080fd5b80632ab4d052116101955780633f3e4c11116101645780633f3e4c111461042157806340c10f191461043457806349dc5e8d146104545780636f6efac61461047457600080fd5b80632ab4d052146103ad5780632f2ff15d146103c3578063313ce567146103e557806336568abe1461040157600080fd5b8063200d2ed2116101d1578063200d2ed2146102b857806323b872dd1461030a578063248a9ca31461032a578063282c51f31461037957600080fd5b806301ffc9a71461020357806306fdde0314610238578063095ea7b31461025a57806318160ddd1461027a575b600080fd5b34801561020f57600080fd5b5061022361021e366004612712565b610796565b60405190151581526020015b60405180910390f35b34801561024457600080fd5b5061024d6107f2565b60405161022f91906127b8565b34801561026657600080fd5b506102236102753660046127f4565b6108c7565b34801561028657600080fd5b507f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace02545b60405190815260200161022f565b3480156102c457600080fd5b506001546102e59073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161022f565b34801561031657600080fd5b5061022361032536600461281e565b6108df565b34801561033657600080fd5b506102aa61034536600461285a565b60009081527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052604090206001015490565b34801561038557600080fd5b506102aa7f3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a84881565b3480156103b957600080fd5b506102aa60005481565b3480156103cf57600080fd5b506103e36103de366004612873565b610903565b005b3480156103f157600080fd5b506040516012815260200161022f565b34801561040d57600080fd5b506103e361041c366004612873565b61094d565b6103e361042f36600461285a565b6109ab565b34801561044057600080fd5b506103e361044f3660046127f4565b610a6e565b34801561046057600080fd5b506103e361046f36600461289f565b610be5565b34801561048057600080fd5b506103e361048f3660046129be565b610c1c565b3480156104a057600080fd5b506102aa6104af36600461289f565b73ffffffffffffffffffffffffffffffffffffffff1660009081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00602052604090205490565b34801561050257600080fd5b506102e5610511366004612ad9565b61100c565b34801561052257600080fd5b50610223610531366004612873565b60009182527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020908152604080842073ffffffffffffffffffffffffffffffffffffffff93909316845291905290205460ff1690565b34801561059457600080fd5b5061024d61104d565b3480156105a957600080fd5b506103e36105b83660046127f4565b61109e565b3480156105c957600080fd5b506102aa600081565b3480156105de57600080fd5b506102236105ed3660046127f4565b61119a565b3480156105fe57600080fd5b506103e361060d36600461289f565b6111a8565b34801561061e57600080fd5b506102aa61062d36600461285a565b6111db565b34801561063e57600080fd5b506102aa7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a681565b34801561067257600080fd5b506103e3610681366004612873565b61121a565b34801561069257600080fd5b506102e561125e565b3480156106a757600080fd5b506102aa6106b6366004612afb565b73ffffffffffffffffffffffffffffffffffffffff91821660009081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace016020908152604080832093909416825291909152205490565b34801561071957600080fd5b5061022361072836600461289f565b6112a0565b34801561073957600080fd5b506102e56112ab565b34801561074e57600080fd5b506102aa7f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b0881565b34801561078257600080fd5b5061022361079136600461289f565b6112d4565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f5a05180f0000000000000000000000000000000000000000000000000000000014806107ec57506107ec826112df565b92915050565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0380546060917f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace009161084390612b25565b80601f016020809104026020016040519081016040528092919081815260200182805461086f90612b25565b80156108bc5780601f10610891576101008083540402835291602001916108bc565b820191906000526020600020905b81548152906001019060200180831161089f57829003601f168201915b505050505091505090565b6000336108d5818585611376565b5060019392505050565b6000336108ed858285611383565b6108f8858585611470565b506001949350505050565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052604090206001015461093d8161151b565b6109478383611528565b50505050565b73ffffffffffffffffffffffffffffffffffffffff8116331461099c576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109a6828261157f565b505050565b7f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b086109d58161151b565b600082905560408051602081018490527f3f3e4c1100000000000000000000000000000000000000000000000000000000917f01d854e8dde9402801a4c6f2840193465752abfad61e0bb7c4258d526ae42e749101604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815290829052610a6291612b78565b60405180910390a25050565b7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6610a988161151b565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663993c2e306040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b299190612bbf565b15610b60576040517f9e87fac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005415801590610ba4575060005482610b987f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace025490565b610ba29190612c10565b115b15610bdb576040517fb1f524eb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109a683836115cd565b7f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b08610c0f8161151b565b610c1882611629565b5050565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff16159067ffffffffffffffff16600081158015610c675750825b905060008267ffffffffffffffff166001148015610c845750303b155b905081158015610c92575080155b15610cc9576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001660011785558315610d2a5784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b855173ffffffffffffffffffffffffffffffffffffffff161580610d665750602086015173ffffffffffffffffffffffffffffffffffffffff16155b80610d895750604086015173ffffffffffffffffffffffffffffffffffffffff16155b80610dac5750606086015173ffffffffffffffffffffffffffffffffffffffff16155b80610dcf5750608086015173ffffffffffffffffffffffffffffffffffffffff16155b15610e06576040517f6e03bddf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610e188660a001518760c0015161171d565b610e437f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b08600061172f565b610e6e7f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a6600061172f565b610e997f3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a848600061172f565b8551610ea790600090611528565b50610ed67f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b088760200151611528565b50610f057f9f2df0fed2c77648de5860a4cc508cd0818c85b8b8a1ab4ceeef8d981c8956a68760400151611528565b50610f347f3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a8488760600151611528565b506080860151600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff90921691909117905560e0860151600055610100860151610f95906117d3565b610fa3866101200151611629565b83156110045784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b505050505050565b60008281527fc1f6fe24621ce81ec5827caf0253cadb74709b061630e6b55e8237170593200060208190526040822061104590846118be565b949350505050565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0480546060917f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace009161084390612b25565b7f3c11d16cbaffd01df69ce1c404f6340ee057498f5f00246190ea54220576a8486110c88161151b565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663993c2e306040518163ffffffff1660e01b8152600401602060405180830381865afa158015611135573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111599190612bbf565b15611190576040517f9e87fac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109a683836118ca565b6000336108d5818585611470565b7f241ecf16d79d0f8dbfb92cbc07fe17840425976cf0667f022fe9877caa831b086111d28161151b565b610c18826117d3565b60008181527fc1f6fe24621ce81ec5827caf0253cadb74709b061630e6b55e8237170593200060208190526040822061121390611926565b9392505050565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b62680060205260409020600101546112548161151b565b610947838361157f565b6000807f8b10dc3a8ffcc75bc517f513160e5993f2893462bfc79b47d34bca818016ba005b5473ffffffffffffffffffffffffffffffffffffffff1692915050565b60006107ec82611930565b6000807f446d7f77ff282b2aa61ea27272a164f51bf50ee624d04aed3bd04af3b9af8f00611283565b60006107ec82611a10565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b0000000000000000000000000000000000000000000000000000000014806107ec57507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316146107ec565b6109a68383836001611aaa565b73ffffffffffffffffffffffffffffffffffffffff83811660009081527f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146109475781811015611461576040517ffb8f41b200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260248101829052604481018390526064015b60405180910390fd5b61094784848484036000611aaa565b73ffffffffffffffffffffffffffffffffffffffff83166114c0576040517f96c6fd1e00000000000000000000000000000000000000000000000000000000815260006004820152602401611458565b73ffffffffffffffffffffffffffffffffffffffff8216611510576040517fec442f0500000000000000000000000000000000000000000000000000000000815260006004820152602401611458565b6109a6838383611c17565b6115258133612029565b50565b60007fc1f6fe24621ce81ec5827caf0253cadb74709b061630e6b55e823717059320008161155685856120d0565b9050801561104557600085815260208390526040902061157690856121f1565b50949350505050565b60007fc1f6fe24621ce81ec5827caf0253cadb74709b061630e6b55e82371705932000816115ad8585612213565b9050801561104557600085815260208390526040902061157690856122f1565b73ffffffffffffffffffffffffffffffffffffffff821661161d576040517fec442f0500000000000000000000000000000000000000000000000000000000815260006004820152602401611458565b610c1860008383611c17565b73ffffffffffffffffffffffffffffffffffffffff8116611676576040517f43396af400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f446d7f77ff282b2aa61ea27272a164f51bf50ee624d04aed3bd04af3b9af8f00805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117845560408051929093168083526020830191909152917fa19fd4029e820c57308467576d8d0296f07717cfcb98941cf8988b25dcd700e391015b60405180910390a1505050565b611725612313565b610c18828261237c565b7f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800600061178a8460009081527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052604090206001015490565b600085815260208490526040808220600101869055519192508491839187917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a450505050565b73ffffffffffffffffffffffffffffffffffffffff8116611820576040517f7e33865300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f8b10dc3a8ffcc75bc517f513160e5993f2893462bfc79b47d34bca818016ba00805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff000000000000000000000000000000000000000083168117845560408051929093168083526020830191909152917f7e053cdc9069fe4f629b6b3fa2a01bb53a9a8305ec11830b259d95e9e75b73049101611710565b600061121383836123df565b73ffffffffffffffffffffffffffffffffffffffff821661191a576040517f96c6fd1e00000000000000000000000000000000000000000000000000000000815260006004820152602401611458565b610c1882600083611c17565b60006107ec825490565b7f446d7f77ff282b2aa61ea27272a164f51bf50ee624d04aed3bd04af3b9af8f0080546000919073ffffffffffffffffffffffffffffffffffffffff163b15611a075780546040517fdf592f7d00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301529091169063df592f7d906024015b602060405180830381865afa1580156119e3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112139190612bbf565b50600092915050565b7f8b10dc3a8ffcc75bc517f513160e5993f2893462bfc79b47d34bca818016ba0080546000919073ffffffffffffffffffffffffffffffffffffffff163b15611a075780546040517ffbac395100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85811660048301529091169063fbac3951906024016119c6565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0073ffffffffffffffffffffffffffffffffffffffff8516611b1b576040517fe602df0500000000000000000000000000000000000000000000000000000000815260006004820152602401611458565b73ffffffffffffffffffffffffffffffffffffffff8416611b6b576040517f94280d6200000000000000000000000000000000000000000000000000000000815260006004820152602401611458565b73ffffffffffffffffffffffffffffffffffffffff808616600090815260018301602090815260408083209388168352929052208390558115611c10578373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92585604051611c0791815260200190565b60405180910390a35b5050505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a1a1ef436040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ca89190612bbf565b15611cdf576040517f9e87fac800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83163314801590611d1b575073ffffffffffffffffffffffffffffffffffffffff82163314155b15611e2657611d2933611a10565b15611d90576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f636d4554483a202773656e64657227206164647265737320626c6f636b6564006044820152606401611458565b611d9933611930565b15611e26576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f636d4554483a202773656e6465722720616464726573732073616e6374696f6e60448201527f65640000000000000000000000000000000000000000000000000000000000006064820152608401611458565b73ffffffffffffffffffffffffffffffffffffffff831615611f2257611e4b83611a10565b15611eb2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f636d4554483a202766726f6d27206164647265737320626c6f636b65640000006044820152606401611458565b611ebb83611930565b15611f22576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f636d4554483a202766726f6d2720616464726573732073616e6374696f6e65646044820152606401611458565b73ffffffffffffffffffffffffffffffffffffffff82161561201e57611f4782611a10565b15611fae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f636d4554483a2027746f27206164647265737320626c6f636b656400000000006044820152606401611458565b611fb782611930565b1561201e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f636d4554483a2027746f2720616464726573732073616e6374696f6e656400006044820152606401611458565b6109a6838383612409565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020908152604080832073ffffffffffffffffffffffffffffffffffffffff8516845290915290205460ff16610c18576040517fe2517d3f00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8216600482015260248101839052604401611458565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020818152604080842073ffffffffffffffffffffffffffffffffffffffff8616855290915282205460ff166121e75760008481526020828152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556121833390565b73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16857f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a460019150506107ec565b60009150506107ec565b60006112138373ffffffffffffffffffffffffffffffffffffffff84166125da565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020818152604080842073ffffffffffffffffffffffffffffffffffffffff8616855290915282205460ff16156121e75760008481526020828152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339287917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a460019150506107ec565b60006112138373ffffffffffffffffffffffffffffffffffffffff8416612629565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005468010000000000000000900460ff1661237a576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b612384612313565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace007f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace036123d08482612c69565b50600481016109478382612c69565b60008260000182815481106123f6576123f6612d83565b9060005260206000200154905092915050565b7f52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace0073ffffffffffffffffffffffffffffffffffffffff841661246457818160020160008282546124599190612c10565b909155506125169050565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260208290526040902054828110156124ea576040517fe450d38c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff861660048201526024810182905260448101849052606401611458565b73ffffffffffffffffffffffffffffffffffffffff851660009081526020839052604090209083900390555b73ffffffffffffffffffffffffffffffffffffffff831661254157600281018054839003905561256d565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020829052604090208054830190555b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516125cc91815260200190565b60405180910390a350505050565b6000818152600183016020526040812054612621575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556107ec565b5060006107ec565b600081815260018301602052604081205480156121e757600061264d600183612db2565b855490915060009061266190600190612db2565b90508082146126c657600086600001828154811061268157612681612d83565b90600052602060002001549050808760000184815481106126a4576126a4612d83565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806126d7576126d7612dc5565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506107ec565b60006020828403121561272457600080fd5b81357fffffffff000000000000000000000000000000000000000000000000000000008116811461121357600080fd5b6000815180845260005b8181101561277a5760208185018101518683018201520161275e565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b6020815260006112136020830184612754565b803573ffffffffffffffffffffffffffffffffffffffff811681146127ef57600080fd5b919050565b6000806040838503121561280757600080fd5b612810836127cb565b946020939093013593505050565b60008060006060848603121561283357600080fd5b61283c846127cb565b925061284a602085016127cb565b9150604084013590509250925092565b60006020828403121561286c57600080fd5b5035919050565b6000806040838503121561288657600080fd5b82359150612896602084016127cb565b90509250929050565b6000602082840312156128b157600080fd5b611213826127cb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610140810167ffffffffffffffff8111828210171561290d5761290d6128ba565b60405290565b600082601f83011261292457600080fd5b813567ffffffffffffffff8082111561293f5761293f6128ba565b604051601f83017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908282118183101715612985576129856128ba565b8160405283815286602085880101111561299e57600080fd5b836020870160208301376000602085830101528094505050505092915050565b6000602082840312156129d057600080fd5b813567ffffffffffffffff808211156129e857600080fd5b9083019061014082860312156129fd57600080fd5b612a056128e9565b612a0e836127cb565b8152612a1c602084016127cb565b6020820152612a2d604084016127cb565b6040820152612a3e606084016127cb565b6060820152612a4f608084016127cb565b608082015260a083013582811115612a6657600080fd5b612a7287828601612913565b60a08301525060c083013582811115612a8a57600080fd5b612a9687828601612913565b60c08301525060e083013560e08201526101009150612ab68284016127cb565b828201526101209150612aca8284016127cb565b91810191909152949350505050565b60008060408385031215612aec57600080fd5b50508035926020909101359150565b60008060408385031215612b0e57600080fd5b612b17836127cb565b9150612896602084016127cb565b600181811c90821680612b3957607f821691505b602082108103612b72577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60408152601a60408201527f7365744d6178546f74616c537570706c792875696e743235362900000000000060608201526080602082015260006112136080830184612754565b600060208284031215612bd157600080fd5b8151801515811461121357600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156107ec576107ec612be1565b601f8211156109a657600081815260208120601f850160051c81016020861015612c4a5750805b601f850160051c820191505b8181101561100457828155600101612c56565b815167ffffffffffffffff811115612c8357612c836128ba565b612c9781612c918454612b25565b84612c23565b602080601f831160018114612cea5760008415612cb45750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555611004565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015612d3757888601518255948401946001909101908401612d18565b5085821015612d7357878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b818103818111156107ec576107ec612be1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea26469706673582212207fa4e218f8563a5f46a8e1e009cab7a39116b04211ffb1fefa000f1b687c1a4664736f6c63430008140033

Verified Source Code Full Match

Compiler: v0.8.20+commit.a1b79de6 EVM: paris Optimization: Yes (1000000 runs)
L1cmETH.sol 160 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

import {ERC20Upgradeable} from "openzeppelin-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import {AccessControlEnumerableUpgradeable} from "openzeppelin-upgradeable/access/extensions/AccessControlEnumerableUpgradeable.sol";

import {SanctionsListClientUpgradeable} from "./ClientSanctionsListUpgradeable.sol";
import {BlockListClientUpgradeable} from "./ClientBlockListUpgradable.sol";
import {IL1StatusRead} from "./interfaces/IMessagingStatus.sol";
import {ProtocolEvents} from "./interfaces/ProtocolEvents.sol";
import {IL1cmETH} from "./interfaces/IL1cmETH.sol";

contract L1cmETH is
    IL1cmETH,
    ProtocolEvents,
    ERC20Upgradeable,
    AccessControlEnumerableUpgradeable,
    BlockListClientUpgradeable,
    SanctionsListClientUpgradeable
{
    // errors
    error Paused();
    error ChainNotExpected();
    error MaxSupplyOutOfBound();
    error UnexpectedInitializeParams();

    /// @notice Role allowed trigger administrative tasks such as setup configurations
    bytes32 public constant MANAGER_ROLE = keccak256("MANAGER_ROLE");

    /// @notice Role to request mint / burn.
    bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
    bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");

    /// @notice The maximum amount of cmETH that can be minted during the original mint process.
    /// @dev This is used as an additional safeguard to create a maximum supply amount in the protocol. As the protocol
    /// scales up this value will be increased to allow for more deposit.
    uint256 public maxTotalSupply;

    // messaging status setup
    address public status;

    struct Init {
        address admin;
        address manager;
        address minter;
        address burner;
        address status;
        string name;
        string symbol;
        uint256 maxSupply;
        address blocklist;
        address sanctionList;
    }

    // @dev _token is the proxy address of L1cmETH
    constructor() {
        _disableInitializers();
    }

    /**
     * @dev Initializes the OFT with the provided name, symbol, and delegate.
     * @dev The delegate typically should be set as the admin of the contract.
     * @dev Ownable is not initialized here on purpose. It should be initialized in the child contract to
     * accommodate the different version of Ownable.
     */
    function initialize(Init memory init) external initializer {
        if (
            init.admin == address(0) ||
            init.manager == address(0) ||
            init.minter == address(0) ||
            init.burner == address(0) ||
            init.status == address(0)
        ) {
            revert UnexpectedInitializeParams();
        }
        __ERC20_init(init.name, init.symbol);

        // set admin roles
        _setRoleAdmin(MANAGER_ROLE, DEFAULT_ADMIN_ROLE);
        _setRoleAdmin(MINTER_ROLE, DEFAULT_ADMIN_ROLE);
        _setRoleAdmin(BURNER_ROLE, DEFAULT_ADMIN_ROLE);

        // grant admin roles
        _grantRole(DEFAULT_ADMIN_ROLE, init.admin);

        // grant sub roles
        _grantRole(MANAGER_ROLE, init.manager);
        _grantRole(MINTER_ROLE, init.minter);
        _grantRole(BURNER_ROLE, init.burner);

        status = init.status;
        maxTotalSupply = init.maxSupply;

        _setBlocklist(init.blocklist);
        _setSanctionsList(init.sanctionList);
    }

    // @notice Original mint when deposit mETH.
    function mint(address _to, uint256 _amount) external onlyRole(MINTER_ROLE) {
        if (IL1StatusRead(status).isOriginalMintBurnPaused()) {
            revert Paused();
        }
        if (maxTotalSupply != 0 && totalSupply() + _amount > maxTotalSupply) {
            revert MaxSupplyOutOfBound();
        }
        _mint(_to, _amount);
    }

    // @notice Original burn when withdraw mETH.
    function burn(address _from, uint256 _amount) external onlyRole(BURNER_ROLE) {
        if (IL1StatusRead(status).isOriginalMintBurnPaused()) {
            revert Paused();
        }
        _burn(_from, _amount);
    }

    /// @notice Sets the maxTotalSupply variable.
    /// Note: We intentionally allow this to be set lower than the current totalSupply so that the amount can be
    /// adjusted downwards by withdraw.
    /// See also {maxTotalSupply}.
    function setMaxTotalSupply(uint256 newMaxTotalSupply) external payable onlyRole(MANAGER_ROLE) {
        maxTotalSupply = newMaxTotalSupply;
        emit ProtocolConfigChanged(
            this.setMaxTotalSupply.selector, "setMaxTotalSupply(uint256)", abi.encode(newMaxTotalSupply)
        );
    }

    function setBlocklist(address _blocklist) external override onlyRole(MANAGER_ROLE) {
        _setBlocklist(_blocklist);
    }

    function setSanctionsList(address _sanctionsList) external override onlyRole(MANAGER_ROLE) {
        _setSanctionsList(_sanctionsList);
    }

    function _update(address from, address to, uint256 value) internal override {
        if (IL1StatusRead(status).isTransferPaused()) {
            revert Paused();
        }
        // Check constraints when `transferFrom` is called to facliitate
        // a transfer between two parties that are not `from` or `to`.
        if (from != msg.sender && to != msg.sender) {
            require(!_isBlocked(msg.sender), "cmETH: 'sender' address blocked");
            require(!_isSanctioned(msg.sender), "cmETH: 'sender' address sanctioned");
        }

        if (from != address(0)) {
            // If not minting
            require(!_isBlocked(from), "cmETH: 'from' address blocked");
            require(!_isSanctioned(from), "cmETH: 'from' address sanctioned");
        }

        if (to != address(0)) {
            // If not burning
            require(!_isBlocked(to), "cmETH: 'to' address blocked");
            require(!_isSanctioned(to), "cmETH: 'to' address sanctioned");
        }
        super._update(from, to, value);
    }
}
IL1cmETH.sol 15 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

interface IL1cmETH {
    /// @notice Mint cmETH when deposit mETH
    /// @param _to The address of the owner.
    /// @param _amount The amount minted.
    function mint(address _to, uint256 _amount) external;

    // @dev Burn cmETH
    /// @notice Burn cmETH when claim mETH withdraw
    /// @param _from The address of the burner
    /// @param _amount The amount will burn
    function burn(address _from, uint256 _amount) external;
}
ClientBlockListUpgradable.sol 106 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

import {AccessControlEnumerableUpgradeable} from "openzeppelin-upgradeable/access/extensions/AccessControlEnumerableUpgradeable.sol";
import {Initializable} from "openzeppelin-upgradeable/proxy/utils/Initializable.sol";
import {IBlockListClient} from "./interfaces/ITransferBlockList.sol";

/**
 * @title BlocklistClient
 * @notice This abstract contract manages state for upgradeable blocklist
 *         clients
 */
abstract contract BlockListClientUpgradeable is Initializable, IBlockListClient, AccessControlEnumerableUpgradeable {
    // errors
    error BlocklistZeroAddress();
    error BlockedAccount();

    /// @custom:storage-location erc7201:storage.BlockList
    struct BlocklistStorage {
        address blocklist;
    }

    // keccak256(abi.encode(uint256(keccak256("storage.BlockList")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant BlocklistStorageLocation = 0x8b10dc3a8ffcc75bc517f513160e5993f2893462bfc79b47d34bca818016ba00;

    function _getBlocklistStorage() internal pure returns (BlocklistStorage storage $) {
        assembly {
            $.slot := BlocklistStorageLocation
        }
    }

    /**
     * @notice Initialize the contract by setting blocklist variable
     *
     * @param _blocklist Address of the blocklist contract
     *
     * @dev Function should be called by the inheriting contract on
     *      initialization
     */
    function __BlocklistClientInitializable_init(address _blocklist) internal onlyInitializing {
        __AccessControlEnumerable_init();
        __BlocklistClientInitializable_init_unchained(_blocklist);
    }

    /**
     * @dev Internal function to future-proof parent linearization. Matches OZ
     *      upgradeable suggestions
     */
    function __BlocklistClientInitializable_init_unchained(address _blocklist) internal onlyInitializing {
        _setBlocklist(_blocklist);
    }

    /**
     * @notice Get the blocklist address for this client
     */
    function blocklist() public view virtual returns (address) {
        BlocklistStorage storage $ = _getBlocklistStorage();
        return $.blocklist;
    }

    /**
     * @notice Sets the blocklist address for this client
     *
     * @param _blocklist The new blocklist address
     */
    function setBlocklist(address _blocklist) external virtual {
        _setBlocklist(_blocklist);
    }

    /**
     * @notice Checks whether an address has been blocked
     *
     * @param account The account to check
     */
    function isBlocked(address account) external view virtual returns (bool) {
        return _isBlocked(account);
    }

    /**
     * @notice Sets the blocklist address for this client
     *
     * @param _blocklist The new blocklist address
     */
    function _setBlocklist(address _blocklist) internal {
        if (_blocklist == address(0)) {
            revert BlocklistZeroAddress();
        }
        BlocklistStorage storage $ = _getBlocklistStorage();
        address oldBlocklist = address($.blocklist);
        $.blocklist = _blocklist;
        emit BlocklistSet(oldBlocklist, _blocklist);
    }

    /**
     * @notice Checks whether an address has been blocked
     *
     * @param account The account to check
     */
    function _isBlocked(address account) internal view returns (bool) {
        BlocklistStorage storage $ = _getBlocklistStorage();
        if ($.blocklist.code.length != 0) {
            return IBlockListClient($.blocklist).isBlocked(account);
        }
        return false;
    }
}
ProtocolEvents.sol 11 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

interface ProtocolEvents {
    /// @notice Emitted when a protocol configuration has been updated.
    /// @param setterSelector The selector of the function that updated the configuration.
    /// @param setterSignature The signature of the function that updated the configuration.
    /// @param value The abi-encoded data passed to the function that updated the configuration. Since this event will
    /// only be emitted by setters, this data corresponds to the updated values in the protocol configuration.
    event ProtocolConfigChanged(bytes4 indexed setterSelector, string setterSignature, bytes value);
}
IMessagingStatus.sol 58 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

interface IStatusRead {
    /// @notice Flag indicating if staking is paused.
    function isTransferPaused() external view returns (bool);
}

interface IL1StatusRead is IStatusRead {
    /// @notice Flag indicating if allocation is paused.
    function isOriginalMintBurnPaused() external view returns (bool);
}

interface IL2StatusRead is IStatusRead {
    /// @notice return exchange rate.
    function exchangeRate() external view returns (uint256);
    /// @notice return capacity.
    function capacity() external view returns (uint256);
    /// @notice return enabled status.
    function enabled() external view returns (bool);
}

interface IStatusWrite {
    /// @notice quote configration send.
    function quote(uint32 eid, bytes calldata message, bytes calldata options) external view returns (uint256, uint256);
    /// @notice Update set TransferPaused status on local.
    function setIsTransferPaused(bool isPaused) external;
    /// @notice Update set TransferPaused status on target chain.
    function setIsTransferPausedFor(uint32 eid, bool isPaused) external payable;
    /// @notice Update set ExchangeRate on target chain.
    function setExchangeRateFor(uint32 eid, uint256 rate) external payable;
    /// @notice Update set Enable on target chain.
    function setEnableFor(uint32 eid, bool flag) external payable;
    /// @notice Update set Bridging Capacity on target chain.
    function setCapFor(uint32 eid, uint256 cap) external payable;
}

interface IL1StatusWrite is IStatusWrite {
    /// @notice Update set OriginalMintBurnPaused status on local.
    function setIsOriginalMintBurnPaused(bool isPaused) external;
}

interface ConfigEvents {
    /// @notice Emitted when a protocol bridging configuration has been updated.
    /// @param setterSelector The selector of the function that updated the configuration.
    /// @param setterSignature The signature of the function that updated the configuration.
    /// @param value The abi-encoded data passed to the function that updated the configuration. Since this event will
    /// only be emitted by setters, this data corresponds to the updated values in the protocol configuration.
    event BridgingConfigChanged(bytes4 indexed setterSelector, string setterSignature, bytes value);
}

interface PauserEvents {
    /// @notice Emitted when a flag has been updated.
    /// @param selector The selector of the flag that was updated.
    /// @param isPaused The new value of the flag.
    /// @param flagName The name of the flag that was updated.
    event FlagUpdated(bytes4 indexed selector, bool indexed isPaused, string flagName);
}
ITransferBlockList.sol 39 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

// @dev inspired by ONDO-USDY
interface IBlockListClient {
    /// @notice Returns the address of the blocklist that this client setup
    function blocklist() external view returns (address);

    /// @notice Update the blocklist address
    function setBlocklist(address registry) external;

    /// @notice Check if a address is blocked or not
    function isBlocked(address account) external view returns (bool);

    /**
     * @dev Event for when the blocklist reference is set
     * @param oldBlocklist The old blocklist
     * @param newBlocklist The new blocklist
     */
    event BlocklistSet(address oldBlocklist, address newBlocklist);
}

interface IBlockList {
    function addToBlocklist(address[] calldata accounts) external;
    function removeFromBlocklist(address[] calldata accounts) external;
    function isBlocked(address account) external view returns (bool);

    /**
     * @notice Event emitted when addresses are added to the blocklist
     * @param accounts The addresses that were added to the blocklist
     */
    event BlockedAddressesAdded(address[] accounts);

    /**
     * @notice Event emitted when addresses are removed from the blocklist
     * @param accounts The addresses that were removed from the blocklist
     */
    event BlockedAddressesRemoved(address[] accounts);
}
ClientSanctionsListUpgradeable.sol 106 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

import {Initializable} from "openzeppelin-upgradeable/proxy/utils/Initializable.sol";
import {ISanctionsListClient} from "./interfaces/ITransferSanctionList.sol";

/**
 * @title SanctionsListClient
 * @notice This abstract contract manages state for upgradeable sanctionsList
 *         clients
 */
abstract contract SanctionsListClientUpgradeable is Initializable, ISanctionsListClient {
    // errors
    /// @notice Error for when caller attempts to set the `sanctionsList` reference to the zero address
    error SanctionsListZeroAddress();
    /// @notice Error for when caller attempts to perform an action on a sanctioned account
    error SanctionedAccount();

    /// @custom:storage-location erc7201:storage.BareVault
    struct SanctionsListStorage {
        address sanctionsList;
    }

    // keccak256(abi.encode(uint256(keccak256("storage.SanctionsList")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant SanctionsListStorageLocation = 0x446d7f77ff282b2aa61ea27272a164f51bf50ee624d04aed3bd04af3b9af8f00;

    function _getSanctionsListStorage() internal pure returns (SanctionsListStorage storage $) {
        assembly {
            $.slot := SanctionsListStorageLocation
        }
    }

    /**
     * @notice Initialize the contract by setting SanctionsList variable
     *
     * @param _sanctionsList Address of the sanctionsList contract
     *
     * @dev Function should be called by the inheriting contract on
     *      initialization
     */
    function __SanctionsListClientInitializable_init(address _sanctionsList) internal onlyInitializing {
        __SanctionsListClientInitializable_init_unchained(_sanctionsList);
    }

    /**
     * @dev Internal function to future-proof parent linearization. Matches OZ
     *      upgradeable suggestions
     */
    function __SanctionsListClientInitializable_init_unchained(address _sanctionsList) internal onlyInitializing {
        _setSanctionsList(_sanctionsList);
    }

    /**
     * @notice Sets the sanctionsList address for this client
     */
    function sanctionsList() public virtual view returns (address) {
        SanctionsListStorage storage $ = _getSanctionsListStorage();
        return $.sanctionsList;
    }

    /**
     * @notice Sets the sanctionsList address for this client
     *
     * @param _sanctionsList The new sanctionsList address
     */
    function setSanctionsList(address _sanctionsList) external virtual {
        _setSanctionsList(_sanctionsList);
    }

    /**
     * @notice Checks whether an address has been blocked
     *
     * @param account The account to check
     */
    function isSanctioned(address account) external virtual view returns (bool) {
        return _isSanctioned(account);
    }

    /**
     * @notice Sets the sanctionsList address for this client
     *
     * @param _sanctionsList The new sanctionsList address
     */
    function _setSanctionsList(address _sanctionsList) internal {
        if (_sanctionsList == address(0)) {
            revert SanctionsListZeroAddress();
        }
        SanctionsListStorage storage $ = _getSanctionsListStorage();
        address oldSanctionsList = address($.sanctionsList);
        $.sanctionsList = _sanctionsList;
        emit SanctionsListSet(oldSanctionsList, _sanctionsList);
    }

    /**
   * @notice Checks whether an address has been blocked
     *
     * @param account The account to check
     */
    function _isSanctioned(address account) internal view returns (bool) {
        SanctionsListStorage storage $ = _getSanctionsListStorage();
        if ($.sanctionsList.code.length != 0) {
            return ISanctionsListClient($.sanctionsList).isSanctioned(account);
        }
        return false;
    }
}
ITransferSanctionList.sol 51 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;

// @dev inspired by ONDO-USDY
interface ISanctionsListClient {
    /// @notice Returns address of the sanctions list that this client setup
    function sanctionsList() external view returns (address);

    /// @notice Update the sanctions list reference
    function setSanctionsList(address sanctionsList) external;

    // @notice check is the address is sanctioned
    function isSanctioned(address addr) external view returns (bool);

    /**
     * @dev Event for when the sanctions list reference is set
     * @param oldSanctionsList The old list
     * @param newSanctionsList The new list
     */
    event SanctionsListSet(address oldSanctionsList, address newSanctionsList);
}

interface IISanctionsList {
    function addToSanctionsList(address[] calldata accounts) external;
    function removeFromSanctionsList(address[] calldata accounts) external;
    function isSanctioned(address account) external view returns (bool);

    /**
     * @dev Event for when the sanctions list reference is set
     * @param addr The address sanctioned
     */
    event SanctionedAddress(address indexed addr);

    /**
     * @dev Event for when the sanctions list reference is set
     * @param addr The address not sanctioned
     */
    event NonSanctionedAddress(address indexed addr);

    /**
     * @dev Event for when the sanctions list reference is set
     * @param addrs The address list sanctioned
     */
    event SanctionedAddressesAdded(address[] addrs);

    /**
     * @dev Event for when the sanctions list reference is set
     * @param addrs The address list not sanctioned
     */
    event SanctionedAddressesRemoved(address[] addrs);
}
IERC20.sol 79 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

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

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

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

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

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

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

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

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}
IAccessControl.sol 98 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)

pragma solidity ^0.8.20;

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControl {
    /**
     * @dev The `account` is missing a role.
     */
    error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);

    /**
     * @dev The caller of a function is not the expected one.
     *
     * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
     */
    error AccessControlBadConfirmation();

    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `callerConfirmation`.
     */
    function renounceRole(bytes32 role, address callerConfirmation) external;
}
draft-IERC6093.sol 161 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;

/**
 * @dev Standard ERC20 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens.
 */
interface IERC20Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC20InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC20InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     * @param allowance Amount of tokens a `spender` is allowed to operate with.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC20InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC20InvalidSpender(address spender);
}

/**
 * @dev Standard ERC721 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens.
 */
interface IERC721Errors {
    /**
     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20.
     * Used in balance queries.
     * @param owner Address of the current owner of a token.
     */
    error ERC721InvalidOwner(address owner);

    /**
     * @dev Indicates a `tokenId` whose `owner` is the zero address.
     * @param tokenId Identifier number of a token.
     */
    error ERC721NonexistentToken(uint256 tokenId);

    /**
     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param tokenId Identifier number of a token.
     * @param owner Address of the current owner of a token.
     */
    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC721InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC721InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param tokenId Identifier number of a token.
     */
    error ERC721InsufficientApproval(address operator, uint256 tokenId);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC721InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC721InvalidOperator(address operator);
}

/**
 * @dev Standard ERC1155 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens.
 */
interface IERC1155Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     * @param tokenId Identifier number of a token.
     */
    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC1155InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC1155InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param owner Address of the current owner of a token.
     */
    error ERC1155MissingApprovalForAll(address operator, address owner);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC1155InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC1155InvalidOperator(address operator);

    /**
     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
     * Used in batch transfers.
     * @param idsLength Length of the array of token identifiers
     * @param valuesLength Length of the array of token amounts
     */
    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}
IERC165.sol 25 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
EnumerableSet.sol 378 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.

pragma solidity ^0.8.20;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```solidity
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 *
 * [WARNING]
 * ====
 * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
 * unusable.
 * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
 *
 * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
 * array of EnumerableSet.
 * ====
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;
        // Position is the index of the value in the `values` array plus 1.
        // Position 0 is used to mean a value is not in the set.
        mapping(bytes32 value => uint256) _positions;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._positions[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We cache the value's position to prevent multiple reads from the same storage slot
        uint256 position = set._positions[value];

        if (position != 0) {
            // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 valueIndex = position - 1;
            uint256 lastIndex = set._values.length - 1;

            if (valueIndex != lastIndex) {
                bytes32 lastValue = set._values[lastIndex];

                // Move the lastValue to the index where the value to delete is
                set._values[valueIndex] = lastValue;
                // Update the tracked position of the lastValue (that was just moved)
                set._positions[lastValue] = position;
            }

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the tracked position for the deleted slot
            delete set._positions[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._positions[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        return set._values[index];
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function _values(Set storage set) private view returns (bytes32[] memory) {
        return set._values;
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
        bytes32[] memory store = _values(set._inner);
        bytes32[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(AddressSet storage set) internal view returns (address[] memory) {
        bytes32[] memory store = _values(set._inner);
        address[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

    /**
     * @dev Returns the value stored at position `index` in the set. O(1).
     *
     * Note that there are no guarantees on the ordering of values inside the
     * array, and it may change when more values are added or removed.
     *
     * Requirements:
     *
     * - `index` must be strictly less than {length}.
     */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(UintSet storage set) internal view returns (uint256[] memory) {
        bytes32[] memory store = _values(set._inner);
        uint256[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }
}
ContextUpgradeable.sol 34 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;
import {Initializable} from "../proxy/utils/Initializable.sol";

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

    function __Context_init_unchained() internal onlyInitializing {
    }
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}
Initializable.sol 228 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)

pragma solidity ^0.8.20;

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
 * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
 * case an upgrade adds a module that needs to be initialized.
 *
 * For example:
 *
 * [.hljs-theme-light.nopadding]
 * ```solidity
 * contract MyToken is ERC20Upgradeable {
 *     function initialize() initializer public {
 *         __ERC20_init("MyToken", "MTK");
 *     }
 * }
 *
 * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
 *     function initializeV2() reinitializer(2) public {
 *         __ERC20Permit_init("MyToken");
 *     }
 * }
 * ```
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
 * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
 * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() {
 *     _disableInitializers();
 * }
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Storage of the initializable contract.
     *
     * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions
     * when using with upgradeable contracts.
     *
     * @custom:storage-location erc7201:openzeppelin.storage.Initializable
     */
    struct InitializableStorage {
        /**
         * @dev Indicates that the contract has been initialized.
         */
        uint64 _initialized;
        /**
         * @dev Indicates that the contract is in the process of being initialized.
         */
        bool _initializing;
    }

    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;

    /**
     * @dev The contract is already initialized.
     */
    error InvalidInitialization();

    /**
     * @dev The contract is not initializing.
     */
    error NotInitializing();

    /**
     * @dev Triggered when the contract has been initialized or reinitialized.
     */
    event Initialized(uint64 version);

    /**
     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
     * `onlyInitializing` functions can be used to initialize parent contracts.
     *
     * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any
     * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in
     * production.
     *
     * Emits an {Initialized} event.
     */
    modifier initializer() {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        // Cache values to avoid duplicated sloads
        bool isTopLevelCall = !$._initializing;
        uint64 initialized = $._initialized;

        // Allowed calls:
        // - initialSetup: the contract is not in the initializing state and no previous version was
        //                 initialized
        // - construction: the contract is initialized at version 1 (no reininitialization) and the
        //                 current contract is just being deployed
        bool initialSetup = initialized == 0 && isTopLevelCall;
        bool construction = initialized == 1 && address(this).code.length == 0;

        if (!initialSetup && !construction) {
            revert InvalidInitialization();
        }
        $._initialized = 1;
        if (isTopLevelCall) {
            $._initializing = true;
        }
        _;
        if (isTopLevelCall) {
            $._initializing = false;
            emit Initialized(1);
        }
    }

    /**
     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
     * used to initialize parent contracts.
     *
     * A reinitializer may be used after the original initialization step. This is essential to configure modules that
     * are added through upgrades and that require initialization.
     *
     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
     * cannot be nested. If one is invoked in the context of another, execution will revert.
     *
     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
     * a contract, executing them in the right order is up to the developer or operator.
     *
     * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.
     *
     * Emits an {Initialized} event.
     */
    modifier reinitializer(uint64 version) {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        if ($._initializing || $._initialized >= version) {
            revert InvalidInitialization();
        }
        $._initialized = version;
        $._initializing = true;
        _;
        $._initializing = false;
        emit Initialized(version);
    }

    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} and {reinitializer} modifiers, directly or indirectly.
     */
    modifier onlyInitializing() {
        _checkInitializing();
        _;
    }

    /**
     * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.
     */
    function _checkInitializing() internal view virtual {
        if (!_isInitializing()) {
            revert NotInitializing();
        }
    }

    /**
     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
     * through proxies.
     *
     * Emits an {Initialized} event the first time it is successfully executed.
     */
    function _disableInitializers() internal virtual {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        if ($._initializing) {
            revert InvalidInitialization();
        }
        if ($._initialized != type(uint64).max) {
            $._initialized = type(uint64).max;
            emit Initialized(type(uint64).max);
        }
    }

    /**
     * @dev Returns the highest version that has been initialized. See {reinitializer}.
     */
    function _getInitializedVersion() internal view returns (uint64) {
        return _getInitializableStorage()._initialized;
    }

    /**
     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
     */
    function _isInitializing() internal view returns (bool) {
        return _getInitializableStorage()._initializing;
    }

    /**
     * @dev Returns a pointer to the storage namespace.
     */
    // solhint-disable-next-line var-name-mixedcase
    function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
        assembly {
            $.slot := INITIALIZABLE_STORAGE
        }
    }
}
IERC20Metadata.sol 26 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";

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

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

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}
ERC20Upgradeable.sol 341 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {ContextUpgradeable} from "../../utils/ContextUpgradeable.sol";
import {IERC20Errors} from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol";
import {Initializable} from "../../proxy/utils/Initializable.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * The default value of {decimals} is 18. To change this, you should override
 * this function so it returns a different value.
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 */
abstract contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20, IERC20Metadata, IERC20Errors {
    /// @custom:storage-location erc7201:openzeppelin.storage.ERC20
    struct ERC20Storage {
        mapping(address account => uint256) _balances;

        mapping(address account => mapping(address spender => uint256)) _allowances;

        uint256 _totalSupply;

        string _name;
        string _symbol;
    }

    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ERC20")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant ERC20StorageLocation = 0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00;

    function _getERC20Storage() private pure returns (ERC20Storage storage $) {
        assembly {
            $.slot := ERC20StorageLocation
        }
    }

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {
        __ERC20_init_unchained(name_, symbol_);
    }

    function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {
        ERC20Storage storage $ = _getERC20Storage();
        $._name = name_;
        $._symbol = symbol_;
    }

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

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

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

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual returns (uint256) {
        ERC20Storage storage $ = _getERC20Storage();
        return $._totalSupply;
    }

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

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

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

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

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

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _transfer(address from, address to, uint256 value) internal {
        if (from == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        if (to == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(from, to, value);
    }

    /**
     * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
     * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
     * this function.
     *
     * Emits a {Transfer} event.
     */
    function _update(address from, address to, uint256 value) internal virtual {
        ERC20Storage storage $ = _getERC20Storage();
        if (from == address(0)) {
            // Overflow check required: The rest of the code assumes that totalSupply never overflows
            $._totalSupply += value;
        } else {
            uint256 fromBalance = $._balances[from];
            if (fromBalance < value) {
                revert ERC20InsufficientBalance(from, fromBalance, value);
            }
            unchecked {
                // Overflow not possible: value <= fromBalance <= totalSupply.
                $._balances[from] = fromBalance - value;
            }
        }

        if (to == address(0)) {
            unchecked {
                // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
                $._totalSupply -= value;
            }
        } else {
            unchecked {
                // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
                $._balances[to] += value;
            }
        }

        emit Transfer(from, to, value);
    }

    /**
     * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
     * Relies on the `_update` mechanism
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _mint(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(address(0), account, value);
    }

    /**
     * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
     * Relies on the `_update` mechanism.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead
     */
    function _burn(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        _update(account, address(0), value);
    }

    /**
     * @dev Sets `value` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     *
     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
     */
    function _approve(address owner, address spender, uint256 value) internal {
        _approve(owner, spender, value, true);
    }

    /**
     * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
     *
     * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
     * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
     * `Approval` event during `transferFrom` operations.
     *
     * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to
     * true using the following override:
     * ```
     * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
     *     super._approve(owner, spender, value, true);
     * }
     * ```
     *
     * Requirements are the same as {_approve}.
     */
    function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
        ERC20Storage storage $ = _getERC20Storage();
        if (owner == address(0)) {
            revert ERC20InvalidApprover(address(0));
        }
        if (spender == address(0)) {
            revert ERC20InvalidSpender(address(0));
        }
        $._allowances[owner][spender] = value;
        if (emitEvent) {
            emit Approval(owner, spender, value);
        }
    }

    /**
     * @dev Updates `owner` s allowance for `spender` based on spent `value`.
     *
     * Does not update the allowance value in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Does not emit an {Approval} event.
     */
    function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            if (currentAllowance < value) {
                revert ERC20InsufficientAllowance(spender, currentAllowance, value);
            }
            unchecked {
                _approve(owner, spender, currentAllowance - value, false);
            }
        }
    }
}
IAccessControlEnumerable.sol 31 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/IAccessControlEnumerable.sol)

pragma solidity ^0.8.20;

import {IAccessControl} from "../IAccessControl.sol";

/**
 * @dev External interface of AccessControlEnumerable declared to support ERC165 detection.
 */
interface IAccessControlEnumerable is IAccessControl {
    /**
     * @dev Returns one of the accounts that have `role`. `index` must be a
     * value between 0 and {getRoleMemberCount}, non-inclusive.
     *
     * Role bearers are not sorted in any particular way, and their ordering may
     * change at any point.
     *
     * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
     * you perform all queries on the same block. See the following
     * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
     * for more information.
     */
    function getRoleMember(bytes32 role, uint256 index) external view returns (address);

    /**
     * @dev Returns the number of accounts that have `role`. Can be used
     * together with {getRoleMember} to enumerate all bearers of a role.
     */
    function getRoleMemberCount(bytes32 role) external view returns (uint256);
}
AccessControlUpgradeable.sol 233 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)

pragma solidity ^0.8.20;

import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol";
import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol";
import {ERC165Upgradeable} from "../utils/introspection/ERC165Upgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms. This is a lightweight version that doesn't allow enumerating role
 * members except through off-chain means by accessing the contract event logs. Some
 * applications may benefit from on-chain enumerability, for those cases see
 * {AccessControlEnumerable}.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```solidity
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```solidity
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
 * to enforce additional security measures for this role.
 */
abstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControl, ERC165Upgradeable {
    struct RoleData {
        mapping(address account => bool) hasRole;
        bytes32 adminRole;
    }

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;


    /// @custom:storage-location erc7201:openzeppelin.storage.AccessControl
    struct AccessControlStorage {
        mapping(bytes32 role => RoleData) _roles;
    }

    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.AccessControl")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant AccessControlStorageLocation = 0x02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800;

    function _getAccessControlStorage() private pure returns (AccessControlStorage storage $) {
        assembly {
            $.slot := AccessControlStorageLocation
        }
    }

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with an {AccessControlUnauthorizedAccount} error including the required role.
     */
    modifier onlyRole(bytes32 role) {
        _checkRole(role);
        _;
    }

    function __AccessControl_init() internal onlyInitializing {
    }

    function __AccessControl_init_unchained() internal onlyInitializing {
    }
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) public view virtual returns (bool) {
        AccessControlStorage storage $ = _getAccessControlStorage();
        return $._roles[role].hasRole[account];
    }

    /**
     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
     * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
     */
    function _checkRole(bytes32 role) internal view virtual {
        _checkRole(role, _msgSender());
    }

    /**
     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
     * is missing `role`.
     */
    function _checkRole(bytes32 role, address account) internal view virtual {
        if (!hasRole(role, account)) {
            revert AccessControlUnauthorizedAccount(account, role);
        }
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
        AccessControlStorage storage $ = _getAccessControlStorage();
        return $._roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * May emit a {RoleGranted} event.
     */
    function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * May emit a {RoleRevoked} event.
     */
    function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been revoked `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `callerConfirmation`.
     *
     * May emit a {RoleRevoked} event.
     */
    function renounceRole(bytes32 role, address callerConfirmation) public virtual {
        if (callerConfirmation != _msgSender()) {
            revert AccessControlBadConfirmation();
        }

        _revokeRole(role, callerConfirmation);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        AccessControlStorage storage $ = _getAccessControlStorage();
        bytes32 previousAdminRole = getRoleAdmin(role);
        $._roles[role].adminRole = adminRole;
        emit RoleAdminChanged(role, previousAdminRole, adminRole);
    }

    /**
     * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleGranted} event.
     */
    function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
        AccessControlStorage storage $ = _getAccessControlStorage();
        if (!hasRole(role, account)) {
            $._roles[role].hasRole[account] = true;
            emit RoleGranted(role, account, _msgSender());
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleRevoked} event.
     */
    function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
        AccessControlStorage storage $ = _getAccessControlStorage();
        if (hasRole(role, account)) {
            $._roles[role].hasRole[account] = false;
            emit RoleRevoked(role, account, _msgSender());
            return true;
        } else {
            return false;
        }
    }
}
ERC165Upgradeable.sol 33 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)

pragma solidity ^0.8.20;

import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import {Initializable} from "../../proxy/utils/Initializable.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 */
abstract contract ERC165Upgradeable is Initializable, IERC165 {
    function __ERC165_init() internal onlyInitializing {
    }

    function __ERC165_init_unchained() internal onlyInitializing {
    }
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}
AccessControlEnumerableUpgradeable.sol 92 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/extensions/AccessControlEnumerable.sol)

pragma solidity ^0.8.20;

import {IAccessControlEnumerable} from "@openzeppelin/contracts/access/extensions/IAccessControlEnumerable.sol";
import {AccessControlUpgradeable} from "../AccessControlUpgradeable.sol";
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import {Initializable} from "../../proxy/utils/Initializable.sol";

/**
 * @dev Extension of {AccessControl} that allows enumerating the members of each role.
 */
abstract contract AccessControlEnumerableUpgradeable is Initializable, IAccessControlEnumerable, AccessControlUpgradeable {
    using EnumerableSet for EnumerableSet.AddressSet;

    /// @custom:storage-location erc7201:openzeppelin.storage.AccessControlEnumerable
    struct AccessControlEnumerableStorage {
        mapping(bytes32 role => EnumerableSet.AddressSet) _roleMembers;
    }

    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.AccessControlEnumerable")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant AccessControlEnumerableStorageLocation = 0xc1f6fe24621ce81ec5827caf0253cadb74709b061630e6b55e82371705932000;

    function _getAccessControlEnumerableStorage() private pure returns (AccessControlEnumerableStorage storage $) {
        assembly {
            $.slot := AccessControlEnumerableStorageLocation
        }
    }

    function __AccessControlEnumerable_init() internal onlyInitializing {
    }

    function __AccessControlEnumerable_init_unchained() internal onlyInitializing {
    }
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev Returns one of the accounts that have `role`. `index` must be a
     * value between 0 and {getRoleMemberCount}, non-inclusive.
     *
     * Role bearers are not sorted in any particular way, and their ordering may
     * change at any point.
     *
     * WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
     * you perform all queries on the same block. See the following
     * https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
     * for more information.
     */
    function getRoleMember(bytes32 role, uint256 index) public view virtual returns (address) {
        AccessControlEnumerableStorage storage $ = _getAccessControlEnumerableStorage();
        return $._roleMembers[role].at(index);
    }

    /**
     * @dev Returns the number of accounts that have `role`. Can be used
     * together with {getRoleMember} to enumerate all bearers of a role.
     */
    function getRoleMemberCount(bytes32 role) public view virtual returns (uint256) {
        AccessControlEnumerableStorage storage $ = _getAccessControlEnumerableStorage();
        return $._roleMembers[role].length();
    }

    /**
     * @dev Overload {AccessControl-_grantRole} to track enumerable memberships
     */
    function _grantRole(bytes32 role, address account) internal virtual override returns (bool) {
        AccessControlEnumerableStorage storage $ = _getAccessControlEnumerableStorage();
        bool granted = super._grantRole(role, account);
        if (granted) {
            $._roleMembers[role].add(account);
        }
        return granted;
    }

    /**
     * @dev Overload {AccessControl-_revokeRole} to track enumerable memberships
     */
    function _revokeRole(bytes32 role, address account) internal virtual override returns (bool) {
        AccessControlEnumerableStorage storage $ = _getAccessControlEnumerableStorage();
        bool revoked = super._revokeRole(role, account);
        if (revoked) {
            $._roleMembers[role].remove(account);
        }
        return revoked;
    }
}

Read Contract

BURNER_ROLE 0x282c51f3 → bytes32
DEFAULT_ADMIN_ROLE 0xa217fddf → bytes32
MANAGER_ROLE 0xec87621c → bytes32
MINTER_ROLE 0xd5391393 → bytes32
allowance 0xdd62ed3e → uint256
balanceOf 0x70a08231 → uint256
blocklist 0xd64e5396 → address
decimals 0x313ce567 → uint8
getRoleAdmin 0x248a9ca3 → bytes32
getRoleMember 0x9010d07c → address
getRoleMemberCount 0xca15c873 → uint256
hasRole 0x91d14854 → bool
isBlocked 0xfbac3951 → bool
isSanctioned 0xdf592f7d → bool
maxTotalSupply 0x2ab4d052 → uint256
name 0x06fdde03 → string
sanctionsList 0xec571c6a → address
status 0x200d2ed2 → address
supportsInterface 0x01ffc9a7 → bool
symbol 0x95d89b41 → string
totalSupply 0x18160ddd → uint256

Write Contract 12 functions

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

approve 0x095ea7b3
address spender
uint256 value
returns: bool
burn 0x9dc29fac
address _from
uint256 _amount
grantRole 0x2f2ff15d
bytes32 role
address account
initialize 0x588570a5
tuple init
mint 0x40c10f19
address _to
uint256 _amount
renounceRole 0x36568abe
bytes32 role
address callerConfirmation
revokeRole 0xd547741f
bytes32 role
address account
setBlocklist 0xaef18ae7
address _blocklist
setMaxTotalSupply 0x3f3e4c11
uint256 newMaxTotalSupply
setSanctionsList 0x49dc5e8d
address _sanctionsList
transfer 0xa9059cbb
address to
uint256 value
returns: bool
transferFrom 0x23b872dd
address from
address to
uint256 value
returns: bool

Recent Transactions

No transactions found for this address