Address Contract Verified
Address
0x9d7aeF0cbcD7B5BAe2ccc4cF69F68443468bf9F6
Balance
0 ETH
Nonce
1
Code Size
11818 bytes
Creator
0x207E8047...82f8 at tx 0x93ec59b8...5f38ff
Indexed Transactions
0
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