Cryo Explorer Ethereum Mainnet

Address Contract Partially Verified

Address 0xbFC07a8C9615FE62979f02cd0D975cAF61ED0d63
Balance 0 ETH
Nonce 1
Code Size 14194 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

14194 bytes
0x608060405234801561000f575f80fd5b50600436106100e5575f3560e01c80637660725e11610088578063efef2d8d11610063578063efef2d8d14610239578063f054effc1461024c578063f48aef331461025f578063fd1454441461027f575f80fd5b80637660725e146101f3578063953d38e714610206578063b67ddc0814610219575f80fd5b806345f8a3ac116100c357806345f8a3ac146101495780634870dd9a146101855780636dc0ae22146101a157806372e23957146101e0575f80fd5b8063127bd749146100e95780632838ccf81461011a57806333323e1414610134575b5f80fd5b6100fc6100f736600461244a565b610292565b6040516001600160e01b031990911681526020015b60405180910390f35b610122600581565b60405160ff9091168152602001610111565b610147610142366004612481565b61061d565b005b6101756101573660046124c9565b6001600160401b0319165f9081526002602052604090205460ff1690565b6040519015158152602001610111565b61018e61271081565b60405161ffff9091168152602001610111565b6101c87f00000000000000000000000085d6bcc74877a1c6fc66a8cd14369f939663f68f81565b6040516001600160a01b039091168152602001610111565b6101476101ee3660046124eb565b61080b565b61014761020136600461259c565b610b39565b61014761021436600461264f565b610d09565b61022c61022736600461244a565b611212565b60405161011191906127ec565b610147610247366004612481565b61154d565b61014761025a3660046129ac565b61189e565b61027261026d366004612a8a565b611a4d565b6040516101119190612aa5565b61014761028d366004612d0a565b611c00565b6001600160401b031981165f9081526002602052604081205460ff166102cb5760405163725a844f60e01b815260040160405180910390fd5b60ff8084165f90815260208190526040902060030154600160a01b9004166103065760405163ae52a1c360e01b815260040160405180910390fd5b60ff83165f9081526001602090815260408083206001600160401b03198616845290915281208054829061033c5761033c612df5565b5f91825260208083206040805161010081018252600790940290910180546001600160401b031981841b1685526001600160e01b0319600160c01b90910460e01b1684840152600181018054835181860281018601855281815295969295938701949192909184015b8282101561044d578382905f5260205f200180546103c290612e09565b80601f01602080910402602001604051908101604052809291908181526020018280546103ee90612e09565b80156104395780601f1061041057610100808354040283529160200191610439565b820191905f5260205f20905b81548152906001019060200180831161041c57829003601f168201915b5050505050815260200190600101906103a5565b505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156104d157602002820191905f5260205f20905f905b82829054906101000a900460ff1660028111156104af576104af61273a565b8152602060019283018181049485019490930390920291018084116104905790505b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561055657602002820191905f5260205f20905f905b82829054906101000a900460ff1660088111156105345761053461273a565b8152602060019283018181049485019490930390920291018084116105155790505b5050509183525050600482015460ff16602082015260058201805460409092019161058090612e09565b80601f01602080910402602001604051908101604052809291908181526020018280546105ac90612e09565b80156105f75780601f106105ce576101008083540402835291602001916105f7565b820191905f5260205f20905b8154815290600101906020018083116105da57829003601f168201915b50505091835250506006919091015460ff16151560209182015201519150505b92915050565b7f00000000000000000000000085d6bcc74877a1c6fc66a8cd14369f939663f68f6001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015610679573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061069d9190612e41565b6001600160a01b0316336001600160a01b03161415801561074f57507f00000000000000000000000085d6bcc74877a1c6fc66a8cd14369f939663f68f6001600160a01b031663d33219b46040518163ffffffff1660e01b8152600401602060405180830381865afa158015610715573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107399190612e41565b6001600160a01b0316336001600160a01b031614155b1561076d57604051632e1cf34f60e11b815260040160405180910390fd5b60ff8084165f9081526001602090815260408083206001600160401b03198716845290915281208054919290919084169081106107ac576107ac612df5565b5f9182526020822060079190910201600601805460ff1916921515929092179091556040516001600160401b031984169160ff8616917fa59f496191c5addda4817b2c663a40be7f4303a8ebedfcb7a5955f1c645c8c609190a3505050565b7f00000000000000000000000085d6bcc74877a1c6fc66a8cd14369f939663f68f6001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015610867573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061088b9190612e41565b6001600160a01b0316336001600160a01b03161415801561093d57507f00000000000000000000000085d6bcc74877a1c6fc66a8cd14369f939663f68f6001600160a01b031663d33219b46040518163ffffffff1660e01b8152600401602060405180830381865afa158015610903573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109279190612e41565b6001600160a01b0316336001600160a01b031614155b1561095b57604051632e1cf34f60e11b815260040160405180910390fd5b60ff8083165f90815260208190526040902060030154600160a01b9004166109965760405163ae52a1c360e01b815260040160405180910390fd5b6109a36060820182612e5c565b90506109b26040830183612e5c565b9050146109d25760405163a55f701560e01b815260040160405180910390fd5b60ff82165f908152600160209081526040822060059290916109f6908501856124c9565b6001600160401b031916815260208101919091526040015f205403610a2e576040516316962da160e31b815260040160405180910390fd5b600160025f610a4060208501856124c9565b6001600160401b031916815260208082019290925260409081015f908120805460ff19169415159490941790935560ff851683526001825282209190610a88908401846124c9565b6001600160401b03191681526020808201929092526040015f9081208054600181018255908252919020829160070201610ac28282613300565b50610ad2905060208201826124c9565b6001600160401b03191660ff83167ff0ac957e2eefd3cf44c1856aaeb78bfed005705a23271b7c352328aeae54b45c610b116040850160208601613413565b610b1e60c0860186612ead565b604051610b2d93929190613456565b60405180910390a35050565b7f00000000000000000000000085d6bcc74877a1c6fc66a8cd14369f939663f68f6001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b95573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bb99190612e41565b6001600160a01b0316336001600160a01b031614158015610c6b57507f00000000000000000000000085d6bcc74877a1c6fc66a8cd14369f939663f68f6001600160a01b031663d33219b46040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c31573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c559190612e41565b6001600160a01b0316336001600160a01b031614155b15610c8957604051632e1cf34f60e11b815260040160405180910390fd5b610cff88888888888080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525050604080516020601f8c018190048102820181019092528a815292508a91508990819084018382808284375f92019190915250899250611fe9915050565b5050505050505050565b60ff82165f9081526001602090815260408083206001600160401b031985168452825280832080548251818502810185019093528083529192909190849084015b82821015611036575f8481526020808220604080516101008101825260078702909201805480831b6001600160401b0319168452600160c01b900460e01b6001600160e01b0319168385015260018101805483518187028101870185528181529496929593870194939192909184015b82821015610e62578382905f5260205f20018054610dd790612e09565b80601f0160208091040260200160405190810160405280929190818152602001828054610e0390612e09565b8015610e4e5780601f10610e2557610100808354040283529160200191610e4e565b820191905f5260205f20905b815481529060010190602001808311610e3157829003601f168201915b505050505081526020019060010190610dba565b50505050815260200160028201805480602002602001604051908101604052809291908181526020018280548015610ee657602002820191905f5260205f20905f905b82829054906101000a900460ff166002811115610ec457610ec461273a565b815260206001928301818104948501949093039092029101808411610ea55790505b5050505050815260200160038201805480602002602001604051908101604052809291908181526020018280548015610f6b57602002820191905f5260205f20905f905b82829054906101000a900460ff166008811115610f4957610f4961273a565b815260206001928301818104948501949093039092029101808411610f2a5790505b5050509183525050600482015460ff166020820152600582018054604090920191610f9590612e09565b80601f0160208091040260200160405190810160405280929190818152602001828054610fc190612e09565b801561100c5780601f10610fe35761010080835404028352916020019161100c565b820191905f5260205f20905b815481529060010190602001808311610fef57829003601f168201915b50505091835250506006919091015460ff1615156020918201529082526001929092019101610d4a565b5050505090505f5b81518160ff16101561120a575f828260ff168151811061106057611060612df5565b6020908102919091010151905061107a60045f888a613481565b611083916134a8565b6001600160e01b03191681602001516001600160e01b031916146110ba57604051633a81518560e01b815260040160405180910390fd5b8060e00151156111f7576004805f5b8360400151518160ff1610156111f35783604001518160ff16815181106110f2576110f2612df5565b6020026020010151518261110691906134e0565b9150736bfd7add62e94ec38556709cb465b8229772db776364eaaa5961112e84868d8f613481565b87604001518560ff168151811061114757611147612df5565b602002602001015188608001518660ff168151811061116857611168612df5565b602002602001015189606001518760ff168151811061118957611189612df5565b60200260200101516040518663ffffffff1660e01b81526004016111b19594939291906134f3565b5f6040518083038186803b1580156111c7575f80fd5b505af41580156111d9573d5f803e3d5ffd5b5050505081925080806111eb9061353f565b9150506110c9565b5050505b50806112028161353f565b91505061103e565b505050505050565b60ff82165f9081526001602090815260408083206001600160401b0319851684528252808320805482518185028101850190935280835260609492939192909184015b82821015611541575f8481526020808220604080516101008101825260078702909201805480831b6001600160401b0319168452600160c01b900460e01b6001600160e01b0319168385015260018101805483518187028101870185528181529496929593870194939192909184015b8282101561136d578382905f5260205f200180546112e290612e09565b80601f016020809104026020016040519081016040528092919081815260200182805461130e90612e09565b80156113595780601f1061133057610100808354040283529160200191611359565b820191905f5260205f20905b81548152906001019060200180831161133c57829003601f168201915b5050505050815260200190600101906112c5565b505050508152602001600282018054806020026020016040519081016040528092919081815260200182805480156113f157602002820191905f5260205f20905f905b82829054906101000a900460ff1660028111156113cf576113cf61273a565b8152602060019283018181049485019490930390920291018084116113b05790505b505050505081526020016003820180548060200260200160405190810160405280929190818152602001828054801561147657602002820191905f5260205f20905f905b82829054906101000a900460ff1660088111156114545761145461273a565b8152602060019283018181049485019490930390920291018084116114355790505b5050509183525050600482015460ff1660208201526005820180546040909201916114a090612e09565b80601f01602080910402602001604051908101604052809291908181526020018280546114cc90612e09565b80156115175780601f106114ee57610100808354040283529160200191611517565b820191905f5260205f20905b8154815290600101906020018083116114fa57829003601f168201915b50505091835250506006919091015460ff1615156020918201529082526001929092019101611255565b50505050905092915050565b7f00000000000000000000000085d6bcc74877a1c6fc66a8cd14369f939663f68f6001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115a9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115cd9190612e41565b6001600160a01b0316336001600160a01b03161415801561167f57507f00000000000000000000000085d6bcc74877a1c6fc66a8cd14369f939663f68f6001600160a01b031663d33219b46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611645573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116699190612e41565b6001600160a01b0316336001600160a01b031614155b1561169d57604051632e1cf34f60e11b815260040160405180910390fd5b60ff83165f9081526001602081815260408084206001600160401b0319871685529091529091208054909182916116d4919061355d565b815481106116e4576116e4612df5565b905f5260205f209060070201818360ff168154811061170557611705612df5565b5f9182526020909120825460079092020180546001600160c01b039092166001600160c01b0319831681178255835463ffffffff600160c01b9182900416026001600160e01b0319909316179190911781556001808301805461176b928401919061215c565b506002828101805461178092840191906121b0565b506003828101805461179592840191906121b0565b50600482810154908201805460ff191660ff9092169190911790556005808201906117c290840182613570565b506006918201549101805460ff191660ff909216151591909117905580548190806117ef576117ef61363f565b5f8281526020812060075f199093019283020180546001600160e01b03191681559061181e6001830182612206565b61182b600283015f612224565b611838600383015f612224565b60048201805460ff19169055611851600583015f612246565b50600601805460ff1916905590556040516001600160401b031984169060ff8616907f586af69549a66c06f5d955bc8686315d173d123752cdb8472b5064026e9a4b2c905f90a350505050565b5f8290036118bf57604051630ef8a34160e11b815260040160405180910390fd5b5f5b60ff8116831115611a4657600484848360ff168181106118e3576118e3612df5565b90506020028101906118f59190612ead565b9050101561191657604051638129bbcd60e01b815260040160405180910390fd5b5f611994868360ff168151811061192f5761192f612df5565b602002602001015186868560ff1681811061194c5761194c612df5565b905060200281019061195e9190612ead565b611967916134a8565b60609190911b6bffffffffffffffffffffffff191660a09190911c6bffffffff0000000000000000161790565b60ff84165f9081526001602090815260408083206001600160401b031985168452909152902054909150156119f9576119f485858460ff168181106119db576119db612df5565b90506020028101906119ed9190612ead565b8584610d09565b611a33565b6001600160401b031981165f9081526002602052604090205460ff1615611a33576040516318fc1be560e11b815260040160405180910390fd5b5080611a3e8161353f565b9150506118c1565b5050505050565b6040805160c080820183525f80835260208084018290526060848601819052808501526080840182905260a0840182905260ff861682528181529084902084519283018552805461ffff8082168552620100009091041691830191909152600181018054939492939192840191611ac390612e09565b80601f0160208091040260200160405190810160405280929190818152602001828054611aef90612e09565b8015611b3a5780601f10611b1157610100808354040283529160200191611b3a565b820191905f5260205f20905b815481529060010190602001808311611b1d57829003601f168201915b50505050508152602001600282018054611b5390612e09565b80601f0160208091040260200160405190810160405280929190818152602001828054611b7f90612e09565b8015611bca5780601f10611ba157610100808354040283529160200191611bca565b820191905f5260205f20905b815481529060010190602001808311611bad57829003601f168201915b5050509183525050600391909101546001600160a01b0381166020830152600160a01b900460ff16151560409091015292915050565b7f00000000000000000000000085d6bcc74877a1c6fc66a8cd14369f939663f68f6001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c5c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611c809190612e41565b6001600160a01b0316336001600160a01b031614158015611d3257507f00000000000000000000000085d6bcc74877a1c6fc66a8cd14369f939663f68f6001600160a01b031663d33219b46040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d1c9190612e41565b6001600160a01b0316336001600160a01b031614155b15611d5057604051632e1cf34f60e11b815260040160405180910390fd5b60ff8089165f90815260208190526040902060030154600160a01b900416611d8b5760405163ae52a1c360e01b815260040160405180910390fd5b8351855114611dad5760405163a55f701560e01b815260040160405180910390fd5b60ff88165f9081526001602090815260408083206001600160401b03198b16845290915290205460041901611df5576040516316962da160e31b815260040160405180910390fd5b5f604051806101000160405280896001600160401b0319168152602001886001600160e01b03191681526020018781526020018681526020018581526020018a60ff16815260200184848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92018290525093855250506001602093840181905260ff8e16835280845260408084206001600160401b03198f16855285528084208054808401825590855293859020865160079095020180548787015160e01c600160c01b026001600160e01b031990911695831c95909517949094178455850151805195965086959394611ef7949286019350019061227d565b5060608201518051611f139160028401916020909101906122c1565b5060808201518051611f2f91600384019160209091019061236b565b5060a082015160048201805460ff191660ff90921691909117905560c08201516005820190611f5e9082613653565b5060e091909101516006909101805491151560ff199283161790556001600160401b031989165f81815260026020526040908190208054909316600117909255905160ff8b16907ff0ac957e2eefd3cf44c1856aaeb78bfed005705a23271b7c352328aeae54b45c90611fd6908b9088908890613456565b60405180910390a3505050505050505050565b61271061ffff861611156120105760405163d173577960e01b815260040160405180910390fd5b61271061ffff8516111561203757604051632e17030160e01b815260040160405180910390fd5b6040805160c08101825261ffff80881682528681166020808401918252838501888152606085018890526001600160a01b0387166080860152600160a0860181905260ff8d165f90815292839052959091208451815493518516620100000263ffffffff199094169416939093179190911782555191929091908201906120be9082613653565b50606082015160028201906120d39082613653565b5060808201516003909101805460a0909301511515600160a01b026001600160a81b03199093166001600160a01b0392831617929092179091556040519082169060ff8816907f8c0185470b7ae77ced8f1bcdcbd7076d5b28c08b3b325f2e03d5c9e8af8f53539061214c9089908990899089906136f9565b60405180910390a3505050505050565b828054828255905f5260205f209081019282156121a0575f5260205f209182015b828111156121a057816121908482613570565b509160010191906001019061217d565b506121ac9291506123dc565b5090565b828054828255905f5260205f2090601f016020900481019282156121fa575f5260205f2091601f016020900482015b828111156121fa5782548255916001019190600101906121df565b506121ac9291506123f8565b5080545f8255905f5260205f209081019061222191906123dc565b50565b5080545f8255601f0160209004905f5260205f209081019061222191906123f8565b50805461225290612e09565b5f825580601f10612261575050565b601f0160209004905f5260205f209081019061222191906123f8565b828054828255905f5260205f209081019282156121a0579160200282015b828111156121a057825182906122b19082613653565b509160200191906001019061229b565b828054828255905f5260205f2090601f016020900481019282156121fa579160200282015f5b8382111561233257835183826101000a81548160ff021916908360028111156123125761231261273a565b021790555092602001926001016020815f010492830192600103026122e7565b801561235e5782816101000a81549060ff02191690556001016020815f01049283019260010302612332565b50506121ac9291506123f8565b828054828255905f5260205f2090601f016020900481019282156121fa579160200282015f5b8382111561233257835183826101000a81548160ff021916908360088111156123bc576123bc61273a565b021790555092602001926001016020815f01049283019260010302612391565b808211156121ac575f6123ef8282612246565b506001016123dc565b5b808211156121ac575f81556001016123f9565b60ff81168114612221575f80fd5b80356124258161240c565b919050565b6001600160401b031981168114612221575f80fd5b80356124258161242a565b5f806040838503121561245b575f80fd5b82356124668161240c565b915060208301356124768161242a565b809150509250929050565b5f805f60608486031215612493575f80fd5b833561249e8161240c565b925060208401356124ae8161242a565b915060408401356124be8161240c565b809150509250925092565b5f602082840312156124d9575f80fd5b81356124e48161242a565b9392505050565b5f80604083850312156124fc575f80fd5b82356125078161240c565b915060208301356001600160401b03811115612521575f80fd5b83016101008186031215612476575f80fd5b803561ffff81168114612425575f80fd5b5f8083601f840112612554575f80fd5b5081356001600160401b0381111561256a575f80fd5b602083019150836020828501011115612581575f80fd5b9250929050565b6001600160a01b0381168114612221575f80fd5b5f805f805f805f8060c0898b0312156125b3575f80fd5b88356125be8161240c565b97506125cc60208a01612533565b96506125da60408a01612533565b955060608901356001600160401b038111156125f4575f80fd5b6126008b828c01612544565b90965094505060808901356001600160401b0381111561261e575f80fd5b61262a8b828c01612544565b90945092505060a089013561263e81612588565b809150509295985092959890939650565b5f805f8060608587031215612662575f80fd5b84356001600160401b03811115612677575f80fd5b61268387828801612544565b90955093505060208501356126978161240c565b915060408501356126a78161242a565b939692955090935050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f82825180855260208501945060208160051b830101602085015f5b8381101561272e57601f198584030188526127188383516126b2565b60209889019890935091909101906001016126fc565b50909695505050505050565b634e487b7160e01b5f52602160045260245ffd5b6003811061275e5761275e61273a565b9052565b5f8151808452602084019350602083015f5b8281101561279a5761278786835161274e565b6020958601959190910190600101612774565b5093949350505050565b6009811061275e5761275e61273a565b5f8151808452602084019350602083015f5b8281101561279a576127d98683516127a4565b60209586019591909101906001016127c6565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b828110156128fa57868503603f19018452815180516001600160401b0319168652602081015161284e60208801826001600160e01b0319169052565b506040810151610100604088015261286a6101008801826126e0565b9050606082015187820360608901526128838282612762565b9150506080820151878203608089015261289d82826127b4565b91505060a08201516128b460a089018260ff169052565b5060c082015187820360c08901526128cc82826126b2565b91505060e082015191506128e460e088018315159052565b9550506020938401939190910190600101612812565b50929695505050505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b038111828210171561294257612942612906565b604052919050565b5f6001600160401b0382111561296257612962612906565b5060051b60200190565b5f8083601f84011261297c575f80fd5b5081356001600160401b03811115612992575f80fd5b6020830191508360208260051b8501011115612581575f80fd5b5f805f80606085870312156129bf575f80fd5b84356001600160401b038111156129d4575f80fd5b8501601f810187136129e4575f80fd5b80356129f76129f28261294a565b61291a565b8082825260208201915060208360051b850101925089831115612a18575f80fd5b6020840193505b82841015612a43578335612a3281612588565b825260209384019390910190612a1f565b965050505060208501356001600160401b03811115612a60575f80fd5b612a6c8782880161296c565b9094509250612a7f90506040860161241a565b905092959194509250565b5f60208284031215612a9a575f80fd5b81356124e48161240c565b6020815261ffff825116602082015261ffff60208301511660408201525f604083015160c06060840152612adc60e08401826126b2565b90506060840151601f19848303016080850152612af982826126b2565b91505060018060a01b0360808501511660a084015260a0840151151560c08401528091505092915050565b6001600160e01b031981168114612221575f80fd5b803561242581612b24565b5f82601f830112612b53575f80fd5b8135612b616129f28261294a565b8082825260208201915060208360051b860101925085831115612b82575f80fd5b602085015b83811015612c205780356001600160401b03811115612ba4575f80fd5b8601603f81018813612bb4575f80fd5b60208101356001600160401b03811115612bd057612bd0612906565b612be3601f8201601f191660200161291a565b8181526040838301018a1015612bf7575f80fd5b816040840160208301375f60208383010152808652505050602083019250602081019050612b87565b5095945050505050565b60038110612221575f80fd5b5f82601f830112612c45575f80fd5b8135612c536129f28261294a565b8082825260208201915060208360051b860101925085831115612c74575f80fd5b602085015b83811015612c20578035612c8c81612c2a565b835260209283019201612c79565b60098110612221575f80fd5b5f82601f830112612cb5575f80fd5b8135612cc36129f28261294a565b8082825260208201915060208360051b860101925085831115612ce4575f80fd5b602085015b83811015612c20578035612cfc81612c9a565b835260209283019201612ce9565b5f805f805f805f8060e0898b031215612d21575f80fd5b612d2a8961241a565b9750612d3860208a0161243f565b9650612d4660408a01612b39565b955060608901356001600160401b03811115612d60575f80fd5b612d6c8b828c01612b44565b95505060808901356001600160401b03811115612d87575f80fd5b612d938b828c01612c36565b94505060a08901356001600160401b03811115612dae575f80fd5b612dba8b828c01612ca6565b93505060c08901356001600160401b03811115612dd5575f80fd5b612de18b828c01612544565b999c989b5096995094979396929594505050565b634e487b7160e01b5f52603260045260245ffd5b600181811c90821680612e1d57607f821691505b602082108103612e3b57634e487b7160e01b5f52602260045260245ffd5b50919050565b5f60208284031215612e51575f80fd5b81516124e481612588565b5f808335601e19843603018112612e71575f80fd5b8301803591506001600160401b03821115612e8a575f80fd5b6020019150600581901b3603821315612581575f80fd5b5f813561061781612b24565b5f808335601e19843603018112612ec2575f80fd5b8301803591506001600160401b03821115612edb575f80fd5b602001915036819003821315612581575f80fd5b634e487b7160e01b5f52601160045260245ffd5b5b81811015612f17575f8155600101612f04565b5050565b5f19600383901b1c191660019190911b1790565b601f821115612f6657805f5260205f20601f840160051c81016020851015612f545750805b611a46601f850160051c830182612f03565b505050565b6001600160401b03831115612f8257612f82612906565b612f9683612f908354612e09565b83612f2f565b5f601f841160018114612fc2575f8515612fb05750838201355b612fba8682612f1b565b845550611a46565b5f83815260208120601f198716915b82811015612ff15786850135825560209485019460019092019101612fd1565b508682101561300d575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b600160401b83111561303357613033612906565b8054838255808410156130b7575f828152602090208481019082015b808210156130b4576130618254612e09565b80156130a857601f81116001811461307b575f84556130a6565b5f84815260209020613098601f840160051c820160018301612f03565b505f84815260208120818655555b505b5060018201915061304f565b50505b505f8181526020812083915b8581101561120a576130d58386612ead565b6130e0818386612f6b565b505060209290920191600191820191016130c3565b600160401b82111561310957613109612906565b805482825580831015612f6657815f5260205f20601f840160051c8101601f85168015613145575f19820180545f198360200360031b1c168155505b50611a46601f840160051c830182612f03565b5f813561061781612c2a565b6001600160401b0383111561317b5761317b612906565b61318583826130f5565b5f8181526020902082908460051c5f5b818110156131ea575f805b60208110156131dd576131cc6131b587613158565b60ff908116600384901b90811b91901b1984161790565b6020969096019591506001016131a0565b5083820155600101613195565b50601f198616808703818814610cff575f805b82811015613222576132116131b588613158565b6020979097019691506001016131fd565b50848401555050505050505050565b5f813561061781612c9a565b6001600160401b0383111561325457613254612906565b61325e83826130f5565b5f8181526020902082908460051c5f5b818110156132ac575f805b602081101561329f5761328e6131b587613231565b602096909601959150600101613279565b508382015560010161326e565b50601f198616808703818814610cff575f805b82811015613222576132d36131b588613231565b6020979097019691506001016132bf565b5f81356106178161240c565b5f81358015158114610617575f80fd5b813561330b8161242a565b81546001600160c01b03191660409190911c17815561335361332f60208401612ea1565b82805463ffffffff60c01b191660209290921c63ffffffff60c01b16919091179055565b6133606040830183612e5c565b61336e81836001860161301f565b505061337d6060830183612e5c565b61338b818360028601613164565b505061339a6080830183612e5c565b6133a881836003860161323d565b50506133ce6133b960a084016132e4565b6004830160ff821660ff198254161781555050565b6133db60c0830183612ead565b6133e9818360058601612f6b565b5050612f176133fa60e084016132f0565b6006830160ff1981541660ff8315151681178255505050565b5f60208284031215613423575f80fd5b81356124e481612b24565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b63ffffffff60e01b84168152604060208201525f61347860408301848661342e565b95945050505050565b5f808585111561348f575f80fd5b8386111561349b575f80fd5b5050820193919092039150565b80356001600160e01b031981169060048410156134d9576001600160e01b0319600485900360031b81901b82161691505b5092915050565b8082018082111561061757610617612eef565b608081525f61350660808301878961342e565b828103602084015261351881876126b2565b91505061352860408301856127a4565b613535606083018461274e565b9695505050505050565b5f60ff821660ff810361355457613554612eef565b60010192915050565b8181038181111561061757610617612eef565b81810361357b575050565b6135858254612e09565b6001600160401b0381111561359c5761359c612906565b6135b0816135aa8454612e09565b84612f2f565b5f601f8211600181146135dc575f83156135ca5750848201545b6135d48482612f1b565b855550611a46565b5f8581526020808220868352908220601f198616925b8381101561361257828601548255600195860195909101906020016135f2565b508583101561362f57818501545f19600388901b60f8161c191681555b5050505050600190811b01905550565b634e487b7160e01b5f52603160045260245ffd5b81516001600160401b0381111561366c5761366c612906565b61367a816135aa8454612e09565b6020601f82116001811461369e575f83156135ca5750848201516135d48482612f1b565b5f84815260208120601f198516915b828110156136cd57878501518255602094850194600190920191016136ad565b50848210156136ea57868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b61ffff8516815261ffff84166020820152608060408201525f61371f60808301856126b2565b828103606084015261373181856126b2565b97965050505050505056fea26469706673582212208a60ddf19e4e8292469e35b889d5ed6ebc751d6667db146afb70df84523dde4c64736f6c634300081a0033

Verified Source Code Partial Match

Compiler: v0.8.26+commit.8a97fa7a EVM: cancun Optimization: Yes (200 runs)
ProposalTypesConfigurator.sol 308 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import {IProposalTypesConfigurator} from "src/interfaces/IProposalTypesConfigurator.sol";
import {IAgoraGovernor} from "src/interfaces/IAgoraGovernor.sol";
import {Validator} from "src/lib/Validator.sol";

/**
 * Contract that stores proposalTypes for the Agora Governor.
 * @custom:security-contact [email protected]
 */
contract ProposalTypesConfigurator is IProposalTypesConfigurator {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event ScopeCreated(uint8 indexed proposalTypeId, bytes24 indexed scopeKey, bytes4 selector, string description);
    event ScopeDisabled(uint8 indexed proposalTypeId, bytes24 indexed scopeKey);
    event ScopeDeleted(uint8 indexed proposalTypeId, bytes24 indexed scopeKey);

    /*//////////////////////////////////////////////////////////////
                           IMMUTABLE STORAGE
    //////////////////////////////////////////////////////////////*/

    IAgoraGovernor public immutable GOVERNOR;

    /// @notice Max value of `quorum` and `approvalThreshold` in `ProposalType`
    uint16 public constant PERCENT_DIVISOR = 10_000;
    // @notice Max length of the `assignedScopes` array
    uint8 public constant MAX_SCOPE_LENGTH = 5;

    /*//////////////////////////////////////////////////////////////
                                STORAGE
    //////////////////////////////////////////////////////////////*/

    mapping(uint8 proposalTypeId => ProposalType) internal _proposalTypes;
    mapping(uint8 proposalTypeId => mapping(bytes24 key => Scope[])) internal _assignedScopes;
    mapping(bytes24 key => bool) internal _scopeExists;

    /*//////////////////////////////////////////////////////////////
                               MODIFIERS
    //////////////////////////////////////////////////////////////*/

    modifier onlyAdminOrTimelock() {
        if (msg.sender != GOVERNOR.admin() && msg.sender != GOVERNOR.timelock()) revert NotAdminOrTimelock();
        _;
    }

    /*//////////////////////////////////////////////////////////////
                              CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    /**
     * @notice Initialize the contract with the governor and proposal types.
     * @param _governor Address of the governor contract.
     * @param _proposalTypesInit Array of ProposalType structs to initialize the contract with.
     */
    constructor(address _governor, ProposalType[] memory _proposalTypesInit) {
        if (_governor == address(0)) revert InvalidGovernor();

        GOVERNOR = IAgoraGovernor(_governor);

        for (uint8 i = 0; i < _proposalTypesInit.length; i++) {
            _setProposalType(
                i,
                _proposalTypesInit[i].quorum,
                _proposalTypesInit[i].approvalThreshold,
                _proposalTypesInit[i].name,
                _proposalTypesInit[i].description,
                _proposalTypesInit[i].module
            );
        }
    }

    /*//////////////////////////////////////////////////////////////
                               FUNCTIONS
    //////////////////////////////////////////////////////////////*/

    /**
     * @notice Get the parameters for a proposal type.
     * @param proposalTypeId Id of the proposal type.
     * @return ProposalType struct of of the proposal type.
     */
    function proposalTypes(uint8 proposalTypeId) external view returns (ProposalType memory) {
        return _proposalTypes[proposalTypeId];
    }

    /**
     * @notice Get the scope that is assigned to a given proposal type.
     * @param proposalTypeId Id of the proposal type.
     * @param scopeKey The function selector + contract address that is the key for a scope.
     * @return Scope struct of the scope.
     */
    function assignedScopes(uint8 proposalTypeId, bytes24 scopeKey) external view returns (Scope[] memory) {
        return _assignedScopes[proposalTypeId][scopeKey];
    }

    /**
     * @notice Returns a boolean if a scope exists.
     * @param key A function selector and contract address that represent the type hash, i.e. 4byte(keccak256("foobar(uint,address)")) + bytes20(contractAddress).
     * @return boolean returns true if the scope is defined.
     */
    function scopeExists(bytes24 key) external view override returns (bool) {
        return _scopeExists[key];
    }

    /**
     * @notice Sets the scope for a given proposal type.
     * @param proposalTypeId Id of the proposal type.
     * @param key A function selector and contract address that represent the type hash, i.e. 4byte(keccak256("foobar(uint,address)")) + bytes20(contractAddress).
     * @param selector A 4 byte function selector.
     * @param parameters The list of byte represented values to be compared.
     * @param comparators List of enumuerated values represent which comparison to use when enforcing limit checks on parameters.
     * @param types List of enumuerated types that map onto each of the supplied parameters.
     * @param description String that's the describes the scope
     */
    function setScopeForProposalType(
        uint8 proposalTypeId,
        bytes24 key,
        bytes4 selector,
        bytes[] memory parameters,
        Comparators[] memory comparators,
        SupportedTypes[] memory types,
        string calldata description
    ) external override onlyAdminOrTimelock {
        if (!_proposalTypes[proposalTypeId].exists) revert InvalidProposalType();
        if (parameters.length != comparators.length) revert InvalidParameterConditions();
        if (_assignedScopes[proposalTypeId][key].length == MAX_SCOPE_LENGTH) revert MaxScopeLengthReached();

        Scope memory scope = Scope(key, selector, parameters, comparators, types, proposalTypeId, description, true);
        _assignedScopes[proposalTypeId][key].push(scope);
        _scopeExists[key] = true;

        emit ScopeCreated(proposalTypeId, key, selector, description);
    }

    /**
     * @notice Set the parameters for a proposal type. Only callable by the admin or timelock.
     * @param proposalTypeId Id of the proposal type
     * @param quorum Quorum percentage, scaled by `PERCENT_DIVISOR`
     * @param approvalThreshold Approval threshold percentage, scaled by `PERCENT_DIVISOR`
     * @param name Name of the proposal type
     * @param description Describes the proposal type
     * @param module Address of module that can only use this proposal type
     */
    function setProposalType(
        uint8 proposalTypeId,
        uint16 quorum,
        uint16 approvalThreshold,
        string calldata name,
        string calldata description,
        address module
    ) external override onlyAdminOrTimelock {
        _setProposalType(proposalTypeId, quorum, approvalThreshold, name, description, module);
    }

    function _setProposalType(
        uint8 proposalTypeId,
        uint16 quorum,
        uint16 approvalThreshold,
        string memory name,
        string memory description,
        address module
    ) internal {
        if (quorum > PERCENT_DIVISOR) revert InvalidQuorum();
        if (approvalThreshold > PERCENT_DIVISOR) revert InvalidApprovalThreshold();

        _proposalTypes[proposalTypeId] = ProposalType(quorum, approvalThreshold, name, description, module, true);

        emit ProposalTypeSet(proposalTypeId, quorum, approvalThreshold, name, description, module);
    }

    /**
     * @notice Adds an additional scope for a given proposal type.
     * @param proposalTypeId Id of the proposal type
     * @param scope An object that contains the scope for a transaction type hash
     */
    function addScopeForProposalType(uint8 proposalTypeId, Scope calldata scope)
        external
        override
        onlyAdminOrTimelock
    {
        if (!_proposalTypes[proposalTypeId].exists) revert InvalidProposalType();
        if (scope.parameters.length != scope.comparators.length) revert InvalidParameterConditions();
        if (_assignedScopes[proposalTypeId][scope.key].length == MAX_SCOPE_LENGTH) revert MaxScopeLengthReached();

        _scopeExists[scope.key] = true;
        _assignedScopes[proposalTypeId][scope.key].push(scope);

        emit ScopeCreated(proposalTypeId, scope.key, scope.selector, scope.description);
    }

    /**
     * @notice Retrives the function selector of a transaction for a given proposal type.
     * @param proposalTypeId Id of the proposal type
     * @param key A type signature of a function and contract address that has a limit specified in a scope
     */
    function getSelector(uint8 proposalTypeId, bytes24 key) public view returns (bytes4 selector) {
        if (!_scopeExists[key]) revert InvalidScope();
        if (!_proposalTypes[proposalTypeId].exists) revert InvalidProposalType();
        Scope memory validScope = _assignedScopes[proposalTypeId][key][0];
        return validScope.selector;
    }

    /**
     * @notice Disables a scopes for all contract + function signatures.
     * @param proposalTypeId the proposal type ID that has the assigned scope.
     * @param scopeKey the contract and function signature representing the scope key
     * @param idx the index of the assigned scope.
     */
    function disableScope(uint8 proposalTypeId, bytes24 scopeKey, uint8 idx) external override onlyAdminOrTimelock {
        _assignedScopes[proposalTypeId][scopeKey][idx].exists = false;
        emit ScopeDisabled(proposalTypeId, scopeKey);
    }

    /**
     * @notice Deletes a scope inside assignedScopes for a proposal type.
     * @param proposalTypeId the proposal type ID that has the assigned scope.
     * @param scopeKey the contract and function signature representing the scope key
     * @param idx the index of the assigned scope.
     */
    function deleteScope(uint8 proposalTypeId, bytes24 scopeKey, uint8 idx) external override onlyAdminOrTimelock {
        Scope[] storage scopeArr = _assignedScopes[proposalTypeId][scopeKey];

        scopeArr[idx] = scopeArr[scopeArr.length - 1];
        scopeArr.pop();

        emit ScopeDeleted(proposalTypeId, scopeKey);
    }

    /**
     * @notice Validates that a proposed transaction conforms to the scope defined in a given proposal type. Note: This
     *   version only supports functions that have for each parameter 32-byte abi encodings, please see the ABI
     *   specification to see which types are not supported. The types that are supported are as follows:
     *      - Uint
     *      - Address
     *      - Bytes32
     * @param proposedTx The calldata of the proposed transaction
     * @param proposalTypeId Id of the proposal type
     * @param key A type signature of a function and contract address that has a limit specified in a scope
     */
    function validateProposedTx(bytes calldata proposedTx, uint8 proposalTypeId, bytes24 key) public view {
        Scope[] memory scopes = _assignedScopes[proposalTypeId][key];

        for (uint8 i = 0; i < scopes.length; i++) {
            Scope memory validScope = scopes[i];
            if (validScope.selector != bytes4(proposedTx[:4])) revert Invalid4ByteSelector();

            if (validScope.exists) {
                uint256 startIdx = 4;
                uint256 endIdx = startIdx;
                for (uint8 j = 0; j < validScope.parameters.length; j++) {
                    endIdx = endIdx + validScope.parameters[j].length;

                    Validator.determineValidation(
                        proposedTx[startIdx:endIdx],
                        validScope.parameters[j],
                        validScope.types[j],
                        validScope.comparators[j]
                    );

                    startIdx = endIdx;
                }
            }
        }
    }

    /**
     * @notice Validates the proposed transactions against the defined scopes based on the proposal type
     * proposal threshold can propose.
     * @param targets The list of target contract addresses.
     * @param calldatas The list of proposed transaction calldata.
     * @param proposalTypeId The type of the proposal.
     */
    function validateProposalData(address[] memory targets, bytes[] calldata calldatas, uint8 proposalTypeId)
        external
        view
    {
        if (calldatas.length == 0) revert InvalidCalldatasLength();

        for (uint8 i = 0; i < calldatas.length; i++) {
            if (calldatas[i].length < 4) revert InvalidCalldata();

            bytes24 scopeKey = _pack(targets[i], bytes4(calldatas[i]));
            if (_assignedScopes[proposalTypeId][scopeKey].length != 0) {
                validateProposedTx(calldatas[i], proposalTypeId, scopeKey);
            } else {
                if (_scopeExists[scopeKey]) {
                    revert InvalidProposedTxForType();
                }
            }
        }
    }

    /**
     * @notice Generates the scope key defined as the contract address combined with the function selector
     * @param contractAddress Address of the contract to be enforced by the scope
     * @param selector A byte4 function selector on the contract to be enforced by the scope
     */
    function _pack(address contractAddress, bytes4 selector) internal pure returns (bytes24 result) {
        bytes20 left = bytes20(contractAddress);
        assembly ("memory-safe") {
            left := and(left, shl(96, not(0)))
            selector := and(selector, shl(224, not(0)))
            result := or(left, shr(160, selector))
        }
    }
}
IProposalTypesConfigurator.sol 113 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

interface IProposalTypesConfigurator {
    /*//////////////////////////////////////////////////////////////
                                 ERRORS
    //////////////////////////////////////////////////////////////*/

    error InvalidQuorum();
    error InvalidApprovalThreshold();
    error InvalidProposalType();
    error InvalidParameterConditions();
    error InvalidScope();
    error NotAdminOrTimelock();
    error NotAdmin();
    error InvalidGovernor();
    error Invalid4ByteSelector();
    error InvalidParamNotEqual();
    error InvalidParamRange();
    error InvalidProposedTxForType();
    error MaxScopeLengthReached();
    error InvalidCalldatasLength();
    error InvalidCalldata();

    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event ProposalTypeSet(
        uint8 indexed proposalTypeId,
        uint16 quorum,
        uint16 approvalThreshold,
        string name,
        string description,
        address indexed module
    );

    /*//////////////////////////////////////////////////////////////
                                STRUCTS
    //////////////////////////////////////////////////////////////*/

    struct ProposalType {
        uint16 quorum;
        uint16 approvalThreshold;
        string name;
        string description;
        address module;
        bool exists;
    }

    enum Comparators {
        EQUAL,
        LESS_THAN,
        GREATER_THAN
    }

    enum SupportedTypes {
        NONE,
        UINT8,
        UINT16,
        UINT32,
        UINT64,
        UINT128,
        UINT256,
        ADDRESS,
        BYTES32
    }

    struct Scope {
        bytes24 key;
        bytes4 selector;
        bytes[] parameters;
        Comparators[] comparators;
        SupportedTypes[] types;
        uint8 proposalTypeId;
        string description;
        bool exists;
    }

    /*//////////////////////////////////////////////////////////////
                               FUNCTIONS
    //////////////////////////////////////////////////////////////*/

    function proposalTypes(uint8 proposalTypeId) external view returns (ProposalType memory);
    function assignedScopes(uint8 proposalTypeId, bytes24 scopeKey) external view returns (Scope[] memory);
    function scopeExists(bytes24 key) external view returns (bool);

    function setProposalType(
        uint8 proposalTypeId,
        uint16 quorum,
        uint16 approvalThreshold,
        string memory name,
        string memory description,
        address module
    ) external;

    function setScopeForProposalType(
        uint8 proposalTypeId,
        bytes24 key,
        bytes4 selector,
        bytes[] memory parameters,
        Comparators[] memory comparators,
        SupportedTypes[] memory types,
        string memory description
    ) external;

    function getSelector(uint8 proposalTypeId, bytes24 key) external returns (bytes4);
    function addScopeForProposalType(uint8 proposalTypeId, Scope calldata scope) external;
    function disableScope(uint8 proposalTypeId, bytes24 scopeKey, uint8 idx) external;
    function deleteScope(uint8 proposalTypeId, bytes24 scopeKey, uint8 idx) external;
    function validateProposedTx(bytes calldata proposedTx, uint8 proposalTypeId, bytes24 key) external;
    function validateProposalData(address[] memory targets, bytes[] memory calldatas, uint8 proposalTypeId) external;
}
IAgoraGovernor.sol 23 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import {IGovernor} from "@openzeppelin/contracts-v4/governance/IGovernor.sol";
import {IVotesUpgradeable} from "@openzeppelin/contracts-upgradeable-v4/governance/utils/IVotesUpgradeable.sol";

abstract contract IAgoraGovernor is IGovernor {
    function manager() external view virtual returns (address);
    function admin() external view virtual returns (address);
    function timelock() external view virtual returns (address);

    function PROPOSAL_TYPES_CONFIGURATOR() external view virtual returns (address);

    function token() external view virtual returns (IVotesUpgradeable);

    function getProposalType(uint256 proposalId) external view virtual returns (uint8);

    function proposalVotes(uint256 proposalId)
        external
        view
        virtual
        returns (uint256 againstVotes, uint256 forVotes, uint256 abstainVotes);
}
Validator.sol 186 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import {IProposalTypesConfigurator} from "src/interfaces/IProposalTypesConfigurator.sol";

library Validator {
    error InvalidParamNotEqual();
    error InvalidParamRange();
    error InvalidComparison();

    /**
     * @notice Compares two byte32 values of the represented type and reverts if condition is not met.
     * @param paramA The first parameter, in this case the one extracted from the calldata
     * @param paramB The second parameter, the one stored on the Scope object
     * @param comparison An enumerated type representing which comparison check should be performed
     */
    function compare(bytes32 paramA, bytes32 paramB, IProposalTypesConfigurator.Comparators comparison) internal pure {
        if (comparison == IProposalTypesConfigurator.Comparators.EQUAL) {
            if (paramA != paramB) revert InvalidParamNotEqual();
        } else if (comparison == IProposalTypesConfigurator.Comparators.LESS_THAN) {
            if (paramA >= paramB) revert InvalidParamRange();
        } else if (comparison == IProposalTypesConfigurator.Comparators.GREATER_THAN) {
            if (paramA <= paramB) revert InvalidParamRange();
        } else {
            revert InvalidComparison();
        }
    }

    /**
     * @notice Given the types and comparison enumeration, determine which type check to use prior to validation.
     * @param param The parameter extracted from the calldata
     * @param scopedParam The parameter stored on the Scope object
     * @param supportedType An enumerated type representing the possible supported types for size checks
     * @param comparison An enumerated type representing which comparison check should be performed
     */
    function determineValidation(
        bytes calldata param,
        bytes calldata scopedParam,
        IProposalTypesConfigurator.SupportedTypes supportedType,
        IProposalTypesConfigurator.Comparators comparison
    ) public pure {
        if (supportedType == IProposalTypesConfigurator.SupportedTypes.UINT8) {
            validate_uint8(param, scopedParam, comparison);
        }

        if (supportedType == IProposalTypesConfigurator.SupportedTypes.UINT16) {
            validate_uint16(param, scopedParam, comparison);
        }

        if (supportedType == IProposalTypesConfigurator.SupportedTypes.UINT32) {
            validate_uint32(param, scopedParam, comparison);
        }

        if (supportedType == IProposalTypesConfigurator.SupportedTypes.UINT64) {
            validate_uint64(param, scopedParam, comparison);
        }

        if (supportedType == IProposalTypesConfigurator.SupportedTypes.UINT128) {
            validate_uint128(param, scopedParam, comparison);
        }

        if (supportedType == IProposalTypesConfigurator.SupportedTypes.UINT256) {
            validate_uint256(param, scopedParam, comparison);
        }

        if (supportedType == IProposalTypesConfigurator.SupportedTypes.ADDRESS) {
            validate_address(param, scopedParam, comparison);
        }

        if (supportedType == IProposalTypesConfigurator.SupportedTypes.BYTES32) {
            validate_bytes32(param, scopedParam, comparison);
        }
    }

    /**
     * @dev Conforms the uint8 type to the necessary size considerations prior to comparison
     */
    function validate_uint8(
        bytes calldata param,
        bytes calldata scopedParam,
        IProposalTypesConfigurator.Comparators comparison
    ) internal pure {
        compare(
            bytes32(bytes1(param[param.length - 1:param.length])),
            bytes32(bytes1(scopedParam[scopedParam.length - 1:scopedParam.length])),
            comparison
        );
    }

    /**
     * @dev Conforms the uint16 type to the necessary size considerations prior to comparison
     */
    function validate_uint16(
        bytes calldata param,
        bytes calldata scopedParam,
        IProposalTypesConfigurator.Comparators comparison
    ) internal pure {
        compare(
            bytes32(bytes2(param[param.length - 2:param.length])),
            bytes32(bytes2(scopedParam[scopedParam.length - 2:scopedParam.length])),
            comparison
        );
    }

    /**
     * @dev Conforms the uint32 type to the necessary size considerations prior to comparison
     */
    function validate_uint32(
        bytes calldata param,
        bytes calldata scopedParam,
        IProposalTypesConfigurator.Comparators comparison
    ) internal pure {
        compare(
            bytes32(bytes4(param[param.length - 4:param.length])),
            bytes32(bytes4(scopedParam[scopedParam.length - 4:scopedParam.length])),
            comparison
        );
    }

    /**
     * @dev Conforms the uint64 type to the necessary size considerations prior to comparison
     */
    function validate_uint64(
        bytes calldata param,
        bytes calldata scopedParam,
        IProposalTypesConfigurator.Comparators comparison
    ) internal pure {
        compare(
            bytes32(bytes8(param[param.length - 8:param.length])),
            bytes32(bytes8(scopedParam[scopedParam.length - 8:scopedParam.length])),
            comparison
        );
    }

    /**
     * @dev Conforms the uint128 type to the necessary size considerations prior to comparison
     */
    function validate_uint128(
        bytes calldata param,
        bytes calldata scopedParam,
        IProposalTypesConfigurator.Comparators comparison
    ) internal pure {
        compare(
            bytes32(bytes16(param[param.length - 16:param.length])),
            bytes32(bytes16(scopedParam[scopedParam.length - 16:scopedParam.length])),
            comparison
        );
    }

    /**
     * @dev Conforms the uint256 type to the necessary size considerations prior to comparison
     */
    function validate_uint256(
        bytes calldata param,
        bytes calldata scopedParam,
        IProposalTypesConfigurator.Comparators comparison
    ) internal pure {
        compare(
            bytes32(param[param.length - 32:param.length]),
            bytes32(scopedParam[scopedParam.length - 32:scopedParam.length]),
            comparison
        );
    }

    /**
     * @dev Conforms the address type to the necessary size considerations prior to comparison
     */
    function validate_address(
        bytes calldata param,
        bytes calldata scopedParam,
        IProposalTypesConfigurator.Comparators comparison
    ) internal pure {
        compare(bytes32(bytes20(param[0:20])), bytes32(bytes20(scopedParam[0:20])), comparison);
    }

    /**
     * @dev Conforms the bytes32 type to the necessary size considerations prior to comparison
     */
    function validate_bytes32(
        bytes calldata param,
        bytes calldata scopedParam,
        IProposalTypesConfigurator.Comparators comparison
    ) internal pure {
        compare(bytes32(param[0:32]), bytes32(scopedParam[0:32]), comparison);
    }
}
IGovernor.sol 276 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (governance/IGovernor.sol)

pragma solidity ^0.8.0;

import "../utils/introspection/ERC165.sol";

/**
 * @dev Interface of the {Governor} core.
 *
 * _Available since v4.3._
 */
abstract contract IGovernor is IERC165 {
    enum ProposalState {
        Pending,
        Active,
        Canceled,
        Defeated,
        Succeeded,
        Queued,
        Expired,
        Executed
    }

    /**
     * @dev Emitted when a proposal is created.
     */
    event ProposalCreated(
        uint256 proposalId,
        address proposer,
        address[] targets,
        uint256[] values,
        string[] signatures,
        bytes[] calldatas,
        uint256 startBlock,
        uint256 endBlock,
        string description
    );

    /**
     * @dev Emitted when a proposal is canceled.
     */
    event ProposalCanceled(uint256 proposalId);

    /**
     * @dev Emitted when a proposal is executed.
     */
    event ProposalExecuted(uint256 proposalId);

    /**
     * @dev Emitted when a vote is cast without params.
     *
     * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.
     */
    event VoteCast(address indexed voter, uint256 proposalId, uint8 support, uint256 weight, string reason);

    /**
     * @dev Emitted when a vote is cast with params.
     *
     * Note: `support` values should be seen as buckets. Their interpretation depends on the voting module used.
     * `params` are additional encoded parameters. Their intepepretation also depends on the voting module used.
     */
    event VoteCastWithParams(
        address indexed voter,
        uint256 proposalId,
        uint8 support,
        uint256 weight,
        string reason,
        bytes params
    );

    /**
     * @notice module:core
     * @dev Name of the governor instance (used in building the ERC712 domain separator).
     */
    function name() public view virtual returns (string memory);

    /**
     * @notice module:core
     * @dev Version of the governor instance (used in building the ERC712 domain separator). Default: "1"
     */
    function version() public view virtual returns (string memory);

    /**
     * @notice module:voting
     * @dev A description of the possible `support` values for {castVote} and the way these votes are counted, meant to
     * be consumed by UIs to show correct vote options and interpret the results. The string is a URL-encoded sequence of
     * key-value pairs that each describe one aspect, for example `support=bravo&quorum=for,abstain`.
     *
     * There are 2 standard keys: `support` and `quorum`.
     *
     * - `support=bravo` refers to the vote options 0 = Against, 1 = For, 2 = Abstain, as in `GovernorBravo`.
     * - `quorum=bravo` means that only For votes are counted towards quorum.
     * - `quorum=for,abstain` means that both For and Abstain votes are counted towards quorum.
     *
     * If a counting module makes use of encoded `params`, it should  include this under a `params` key with a unique
     * name that describes the behavior. For example:
     *
     * - `params=fractional` might refer to a scheme where votes are divided fractionally between for/against/abstain.
     * - `params=erc721` might refer to a scheme where specific NFTs are delegated to vote.
     *
     * NOTE: The string can be decoded by the standard
     * https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams[`URLSearchParams`]
     * JavaScript class.
     */
    // solhint-disable-next-line func-name-mixedcase
    function COUNTING_MODE() public pure virtual returns (string memory);

    /**
     * @notice module:core
     * @dev Hashing function used to (re)build the proposal id from the proposal details..
     */
    function hashProposal(
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        bytes32 descriptionHash
    ) public pure virtual returns (uint256);

    /**
     * @notice module:core
     * @dev Current state of a proposal, following Compound's convention
     */
    function state(uint256 proposalId) public view virtual returns (ProposalState);

    /**
     * @notice module:core
     * @dev Block number used to retrieve user's votes and quorum. As per Compound's Comp and OpenZeppelin's
     * ERC20Votes, the snapshot is performed at the end of this block. Hence, voting for this proposal starts at the
     * beginning of the following block.
     */
    function proposalSnapshot(uint256 proposalId) public view virtual returns (uint256);

    /**
     * @notice module:core
     * @dev Block number at which votes close. Votes close at the end of this block, so it is possible to cast a vote
     * during this block.
     */
    function proposalDeadline(uint256 proposalId) public view virtual returns (uint256);

    /**
     * @notice module:user-config
     * @dev Delay, in number of block, between the proposal is created and the vote starts. This can be increassed to
     * leave time for users to buy voting power, or delegate it, before the voting of a proposal starts.
     */
    function votingDelay() public view virtual returns (uint256);

    /**
     * @notice module:user-config
     * @dev Delay, in number of blocks, between the vote start and vote ends.
     *
     * NOTE: The {votingDelay} can delay the start of the vote. This must be considered when setting the voting
     * duration compared to the voting delay.
     */
    function votingPeriod() public view virtual returns (uint256);

    /**
     * @notice module:user-config
     * @dev Minimum number of cast voted required for a proposal to be successful.
     *
     * Note: The `blockNumber` parameter corresponds to the snapshot used for counting vote. This allows to scale the
     * quorum depending on values such as the totalSupply of a token at this block (see {ERC20Votes}).
     */
    function quorum(uint256 blockNumber) public view virtual returns (uint256);

    /**
     * @notice module:reputation
     * @dev Voting power of an `account` at a specific `blockNumber`.
     *
     * Note: this can be implemented in a number of ways, for example by reading the delegated balance from one (or
     * multiple), {ERC20Votes} tokens.
     */
    function getVotes(address account, uint256 blockNumber) public view virtual returns (uint256);

    /**
     * @notice module:reputation
     * @dev Voting power of an `account` at a specific `blockNumber` given additional encoded parameters.
     */
    function getVotesWithParams(
        address account,
        uint256 blockNumber,
        bytes memory params
    ) public view virtual returns (uint256);

    /**
     * @notice module:voting
     * @dev Returns whether `account` has cast a vote on `proposalId`.
     */
    function hasVoted(uint256 proposalId, address account) public view virtual returns (bool);

    /**
     * @dev Create a new proposal. Vote start {IGovernor-votingDelay} blocks after the proposal is created and ends
     * {IGovernor-votingPeriod} blocks after the voting starts.
     *
     * Emits a {ProposalCreated} event.
     */
    function propose(
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        string memory description
    ) public virtual returns (uint256 proposalId);

    /**
     * @dev Execute a successful proposal. This requires the quorum to be reached, the vote to be successful, and the
     * deadline to be reached.
     *
     * Emits a {ProposalExecuted} event.
     *
     * Note: some module can modify the requirements for execution, for example by adding an additional timelock.
     */
    function execute(
        address[] memory targets,
        uint256[] memory values,
        bytes[] memory calldatas,
        bytes32 descriptionHash
    ) public payable virtual returns (uint256 proposalId);

    /**
     * @dev Cast a vote
     *
     * Emits a {VoteCast} event.
     */
    function castVote(uint256 proposalId, uint8 support) public virtual returns (uint256 balance);

    /**
     * @dev Cast a vote with a reason
     *
     * Emits a {VoteCast} event.
     */
    function castVoteWithReason(
        uint256 proposalId,
        uint8 support,
        string calldata reason
    ) public virtual returns (uint256 balance);

    /**
     * @dev Cast a vote with a reason and additional encoded parameters
     *
     * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.
     */
    function castVoteWithReasonAndParams(
        uint256 proposalId,
        uint8 support,
        string calldata reason,
        bytes memory params
    ) public virtual returns (uint256 balance);

    /**
     * @dev Cast a vote using the user's cryptographic signature.
     *
     * Emits a {VoteCast} event.
     */
    function castVoteBySig(
        uint256 proposalId,
        uint8 support,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual returns (uint256 balance);

    /**
     * @dev Cast a vote with a reason and additional encoded parameters using the user's cryptographic signature.
     *
     * Emits a {VoteCast} or {VoteCastWithParams} event depending on the length of params.
     */
    function castVoteWithReasonAndParamsBySig(
        uint256 proposalId,
        uint8 support,
        string calldata reason,
        bytes memory params,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual returns (uint256 balance);
}
IVotesUpgradeable.sol 61 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (governance/utils/IVotes.sol)
pragma solidity ^0.8.0;

/**
 * @dev Common interface for {ERC20Votes}, {ERC721Votes}, and other {Votes}-enabled contracts.
 *
 * _Available since v4.5._
 */
interface IVotesUpgradeable {
    /**
     * @dev Emitted when an account changes their delegate.
     */
    event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);

    /**
     * @dev Emitted when a token transfer or delegate change results in changes to a delegate's number of votes.
     */
    event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);

    /**
     * @dev Returns the current amount of votes that `account` has.
     */
    function getVotes(address account) external view returns (uint256);

    /**
     * @dev Returns the amount of votes that `account` had at the end of a past block (`blockNumber`).
     */
    function getPastVotes(address account, uint256 blockNumber) external view returns (uint256);

    /**
     * @dev Returns the total supply of votes available at the end of a past block (`blockNumber`).
     *
     * NOTE: This value is the sum of all available votes, which is not necessarily the sum of all delegated votes.
     * Votes that have not been delegated are still part of total supply, even though they would not participate in a
     * vote.
     */
    function getPastTotalSupply(uint256 blockNumber) external view returns (uint256);

    /**
     * @dev Returns the delegate that `account` has chosen.
     */
    function delegates(address account) external view returns (address);

    /**
     * @dev Delegates votes from the sender to `delegatee`.
     */
    function delegate(address delegatee) external;

    /**
     * @dev Delegates votes from signer to `delegatee`.
     */
    function delegateBySig(
        address delegatee,
        uint256 nonce,
        uint256 expiry,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;
}
ERC165.sol 29 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;

import "./IERC165.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);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}
IERC165.sol 25 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @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);
}

Read Contract

GOVERNOR 0x6dc0ae22 → address
MAX_SCOPE_LENGTH 0x2838ccf8 → uint8
PERCENT_DIVISOR 0x4870dd9a → uint16
assignedScopes 0xb67ddc08 → tuple[]
getSelector 0x127bd749 → bytes4
proposalTypes 0xf48aef33 → tuple
scopeExists 0x45f8a3ac → bool
validateProposalData 0xf054effc
validateProposedTx 0x953d38e7

Write Contract 5 functions

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

addScopeForProposalType 0x3470e318
uint8 proposalTypeId
tuple scope
deleteScope 0xefef2d8d
uint8 proposalTypeId
bytes24 scopeKey
uint8 idx
disableScope 0x33323e14
uint8 proposalTypeId
bytes24 scopeKey
uint8 idx
setProposalType 0x7660725e
uint8 proposalTypeId
uint16 quorum
uint16 approvalThreshold
string name
string description
address module
setScopeForProposalType 0xfd145444
uint8 proposalTypeId
bytes24 key
bytes4 selector
bytes[] parameters
uint8[] comparators
uint8[] types
string description

Recent Transactions

No transactions found for this address