Address Contract Verified
Address
0xcafea466bF6dEFe480cdd54056C020c63b7DA830
Balance
0 ETH
Nonce
1
Code Size
13079 bytes
Creator
0xfac70116...3C3F at tx 0x1babdf43...414a97
Indexed Transactions
0 (1 on-chain, 1.4% indexed)
Contract Bytecode
13079 bytes
0x608060405260043610610130575f3560e01c806392be0d83116100a8578063b1610d7e1161006d578063b1610d7e146103e4578063c7f758a8146103fa578063da35c66414610426578063df220e511461043a578063eddd9d8214610459578063fe0d94c11461048c575f5ffd5b806392be0d831461034a578063943e82161461035e578063a6c266031461037d578063a730117e14610399578063ac9650d8146103b8575f5ffd5b806349330cb8116100f957806349330cb8146102085780634a5bcbf8146102345780636d4443621461024a5780637b1039991461025e5780638341d6ef146102a957806389ebae241461032b575f5ffd5b8062a6e74b146101345780631780a65114610169578063229acb171461019957806337bfaa1b146101c557806340e58ee5146101e7575b5f5ffd5b34801561013f575f5ffd5b5061015361014e3660046128b7565b61049f565b6040516101609190612989565b60405180910390f35b348015610174575f5ffd5b506101886101833660046128b7565b6105c9565b604051610160959493929190612a68565b3480156101a4575f5ffd5b506101b86101b33660046128b7565b6108cc565b6040516101609190612ab2565b3480156101d0575f5ffd5b506101d9600581565b604051908152602001610160565b3480156101f2575f5ffd5b506102066102013660046128b7565b61096b565b005b348015610213575f5ffd5b50610227610222366004612ac4565b610c84565b6040516101609190612ae4565b34801561023f575f5ffd5b506101d96201518081565b348015610255575f5ffd5b506101d9600f81565b348015610269575f5ffd5b506102917f000000000000000000000000cafea2c575550512582090aa06d0a069e7236b9e81565b6040516001600160a01b039091168152602001610160565b3480156102b4575f5ffd5b5061031e6102c33660046128b7565b60408051606080820183525f808352602080840182905292840181905293845260048252928290208251938401835280546001600160601b038082168652600160601b90910481169285019290925260010154169082015290565b6040516101609190612b11565b348015610336575f5ffd5b506101d9610345366004612c13565b610d00565b348015610355575f5ffd5b506101d9600381565b348015610369575f5ffd5b50610206610378366004612cfb565b61121d565b348015610388575f5ffd5b506101d968056bc75e2d6310000081565b3480156103a4575f5ffd5b506101d96103b3366004612d40565b611839565b3480156103c3575f5ffd5b506103d76103d2366004612d9b565b6118d8565b6040516101609190612dd9565b3480156103ef575f5ffd5b506101d96203f48081565b348015610405575f5ffd5b506104196104143660046128b7565b611a11565b6040516101609190612e3c565b348015610431575f5ffd5b506101d95f5481565b348015610445575f5ffd5b506101d9610454366004612e4a565b611af2565b348015610464575f5ffd5b506102917f0000000000000000000000005407381b6c251cfd498ccd4a1d877739cb7960b881565b61020661049a3660046128b7565b611be9565b606060035f8381526020019081526020015f20805480602002602001604051908101604052809291908181526020015f905b828210156105be575f848152602090819020604080516060810182526002860290920180546001600160a01b0381168452600160a01b90046001600160601b0316938301939093526001830180549293929184019161052f90612eb4565b80601f016020809104026020016040519081016040528092919081815260200182805461055b90612eb4565b80156105a65780601f1061057d576101008083540402835291602001916105a6565b820191905f5260205f20905b81548152906001019060200180831161058957829003601f168201915b505050505081525050815260200190600101906104d1565b505050509050919050565b6040805160a0810182525f808252602082018190529181018290526060810182905260808101829052606080610617604080516060810182525f808252602082018190529181019190915290565b5f8681526001602081815260408084206002835281852060038452828620600490945294829020825160a0810190935281548c96929592949391928691839160ff9091169081111561066b5761066b6129a2565b600181111561067c5761067c6129a2565b81528154602090910190610100900460ff16600281111561069f5761069f6129a2565b60028111156106b0576106b06129a2565b8152905463ffffffff62010000820481166020840152600160301b820481166040840152600160501b90910416606090910152835490945083906106f390612eb4565b80601f016020809104026020016040519081016040528092919081815260200182805461071f90612eb4565b801561076a5780601f106107415761010080835404028352916020019161076a565b820191905f5260205f20905b81548152906001019060200180831161074d57829003601f168201915b5050505050925081805480602002602001604051908101604052809291908181526020015f905b8282101561087e575f848152602090819020604080516060810182526002860290920180546001600160a01b0381168452600160a01b90046001600160601b031693830193909352600183018054929392918401916107ef90612eb4565b80601f016020809104026020016040519081016040528092919081815260200182805461081b90612eb4565b80156108665780601f1061083d57610100808354040283529160200191610866565b820191905f5260205f20905b81548152906001019060200180831161084957829003601f168201915b50505050508152505081526020019060010190610791565b50506040805160608101825285546001600160601b038082168352600160601b909104811660208301526001909601549095169085015250959c949b50929950919750909550909350505050565b5f8181526002602052604090208054606091906108e890612eb4565b80601f016020809104026020016040519081016040528092919081815260200182805461091490612eb4565b801561095f5780601f106109365761010080835404028352916020019161095f565b820191905f5260205f20905b81548152906001019060200180831161094257829003601f168201915b50505050509050919050565b604051632246488d60e01b81523360048201527f000000000000000000000000cafea2c575550512582090aa06d0a069e7236b9e6001600160a01b031690632246488d90602401602060405180830381865afa1580156109cd573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109f19190612eec565b610a0e576040516315c171d760e31b815260040160405180910390fd5b5f818152600160208190526040808320815160a08101909252805491929091839160ff90911690811115610a4457610a446129a2565b6001811115610a5557610a556129a2565b81528154602090910190610100900460ff166002811115610a7857610a786129a2565b6002811115610a8957610a896129a2565b8152905463ffffffff62010000820481166020840152600160301b82048116604080850191909152600160501b909204811660609093019290925282015191925016610ae85760405163635e873760e01b815260040160405180910390fd5b5f81516001811115610afc57610afc6129a2565b14610b1a57604051632f099b2b60e21b815260040160405180910390fd5b600181602001516002811115610b3257610b326129a2565b03610b50576040516351618d5360e01b815260040160405180910390fd5b600281602001516002811115610b6857610b686129a2565b03610b86576040516346c48e3760e11b815260040160405180910390fd5b600260208201819052505f828152600160208190526040909120825181548493839160ff1916908381811115610bbe57610bbe6129a2565b021790555060208201518154829061ff001916610100836002811115610be657610be66129a2565b02179055506040828101518254606085015160809095015169ffffffffffffffff0000199091166201000063ffffffff9384160263ffffffff60301b191617600160301b958316959095029490941763ffffffff60501b1916600160501b9190941602929092179055518281527f789cf55be980739dad1d0699b93b58e806b51c9d96619bfa8fe0a28abaa7b30c9060200160405180910390a15050565b6040805180820182525f808252602080830182905285825260058152838220858352905282902082518084019093528054919291829060ff166002811115610cce57610cce6129a2565b6002811115610cdf57610cdf6129a2565b8152905461010090046001600160601b031660209091015290505b92915050565b60405163288c314960e21b81523360048201525f907f000000000000000000000000cafea2c575550512582090aa06d0a069e7236b9e6001600160a01b03169063a230c52490602401602060405180830381865afa158015610d64573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d889190612eec565b610da55760405163148fe22160e11b815260040160405180910390fd5b5f610daf336122f0565b905068056bc75e2d631000008111610dda576040516372db778960e11b815260040160405180910390fd5b5f85516001600160401b03811115610df457610df4612b1f565b604051908082528060200260200182016040528015610e4057816020015b60408051606080820183525f808352602083015291810191909152815260200190600190039081610e125790505b5090505f5b86518110156111d157868181518110610e6057610e60612f0b565b602002602001015160200151878281518110610e7e57610e7e612f0b565b60200260200101515f015103610ea7576040516337cf6cbd60e01b815260040160405180910390fd5b868181518110610eb957610eb9612f0b565b60200260200101515f01515f14158015610ef05750868181518110610ee057610ee0612f0b565b6020026020010151602001515f14155b610f0d576040516337cf6cbd60e01b815260040160405180910390fd5b7f000000000000000000000000cafea2c575550512582090aa06d0a069e7236b9e6001600160a01b031663b7f0dc25888381518110610f4e57610f4e612f0b565b60200260200101515f01516040518263ffffffff1660e01b8152600401610f7791815260200190565b602060405180830381865afa158015610f92573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fb69190612eec565b610fd3576040516337cf6cbd60e01b815260040160405180910390fd5b5f6001600160a01b03167f000000000000000000000000cafea2c575550512582090aa06d0a069e7236b9e6001600160a01b0316639029444a89848151811061101e5761101e612f0b565b6020026020010151602001516040518263ffffffff1660e01b815260040161104891815260200190565b602060405180830381865afa158015611063573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110879190612f1f565b6001600160a01b0316036110ae5760405163148fe22160e11b815260040160405180910390fd5b60405180606001604052807f000000000000000000000000cafea2c575550512582090aa06d0a069e7236b9e6001600160a01b031681526020015f6001600160601b031681526020017f000000000000000000000000cafea2c575550512582090aa06d0a069e7236b9e5063e333cc8560e01b89848151811061113357611133612f0b565b60200260200101515f01518a858151811061115057611150612f0b565b602002602001015160200151604051602401611176929190918252602082015260400190565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152905282518390839081106111be576111be612f0b565b6020908102919091010152600101610e45565b5061121360018287878080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061244292505050565b9695505050505050565b5f828152600160208190526040808320815160a08101909252805491929091839160ff90911690811115611253576112536129a2565b6001811115611264576112646129a2565b81528154602090910190610100900460ff166002811115611287576112876129a2565b6002811115611298576112986129a2565b8152905463ffffffff62010000820481166020840152600160301b82048116604080850191909152600160501b9092048116606090930192909252820151919250166112f75760405163635e873760e01b815260040160405180910390fd5b806060015163ffffffff16421061132157604051637c065cc560e01b815260040160405180910390fd5b600181602001516002811115611339576113396129a2565b03611357576040516351618d5360e01b815260040160405180910390fd5b60028160200151600281111561136f5761136f6129a2565b0361138d576040516346c48e3760e11b815260040160405180910390fd5b60405163c269014b60e01b81523360048201525f907f000000000000000000000000cafea2c575550512582090aa06d0a069e7236b9e6001600160a01b03169063c269014b90602401602060405180830381865afa1580156113f1573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114159190612f3a565b90505f81116114375760405163148fe22160e11b815260040160405180910390fd5b5f808351600181111561144c5761144c6129a2565b1490505f8161145b57826114e1565b6040516302a6edc760e31b81523360048201527f000000000000000000000000cafea2c575550512582090aa06d0a069e7236b9e6001600160a01b0316906315376e3890602401602060405180830381865afa1580156114bd573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114e19190612f3a565b5f87815260056020908152604080832084845290915290205490915061010090046001600160601b03161561152957604051637c9a1cf960e01b815260040160405180910390fd5b5f611547836115405761153b336122f0565b61268e565b600161268e565b90506040518060400160405280876002811115611566576115666129a2565b81526001600160601b0383166020918201525f8981526005825260408082208683529092522081518154829060ff191660018360028111156115aa576115aa6129a2565b02179055506020919091015181546001600160601b03909116610100026cffffffffffffffffffffffff001990911617905560018660028111156115f0576115f06129a2565b0361164a575f8781526004602052604090208054829190600c90611625908490600160601b90046001600160601b0316612f65565b92506101000a8154816001600160601b0302191690836001600160601b031602179055505b5f86600281111561165d5761165d6129a2565b036116ad575f87815260046020526040812080548392906116889084906001600160601b0316612f65565b92506101000a8154816001600160601b0302191690836001600160601b031602179055505b60028660028111156116c1576116c16129a2565b03611714575f87815260046020526040812060010180548392906116ef9084906001600160601b0316612f65565b92506101000a8154816001600160601b0302191690836001600160601b031602179055505b82801561174057505f878152600460205260409020546003600160601b9091046001600160601b031610155b156117c85761175a6117556201518042612f84565b6126f5565b63ffffffff16608086018190525f888152600160205260409020805463ffffffff60501b1916600160501b909202919091179055611797426126f5565b5f888152600160205260409020805463ffffffff92909216600160301b0263ffffffff60301b199092169190911790555b826117e1576117e133866080015163ffffffff16612759565b8451829060018111156117f6576117f66129a2565b887fede9ccb663cfddaf5e5062448b786c6b485a6a70ca6ffc962a7ca62af422f52d8985604051611828929190612f97565b60405180910390a450505050505050565b60405163288c314960e21b81526001600160a01b0382811660048301525f917f000000000000000000000000cafea2c575550512582090aa06d0a069e7236b9e9091169063a230c52490602401602060405180830381865afa1580156118a1573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118c59190612eec565b6118cf575f610cfa565b610cfa826122f0565b606081806001600160401b038111156118f3576118f3612b1f565b60405190808252806020026020018201604052801561192657816020015b60608152602001906001900390816119115790505b5091505f5b81811015611a09575f803087878581811061194857611948612f0b565b905060200281019061195a9190612fbc565b604051611968929190612ffe565b5f60405180830381855af49150503d805f81146119a0576040519150601f19603f3d011682016040523d82523d5f602084013e6119a5565b606091505b5091509150816119e15780515f8190036119da5760405163f1a8c42d60e01b8152600481018590526024015b60405180910390fd5b8060208301fd5b808584815181106119f4576119f4612f0b565b6020908102919091010152505060010161192b565b505092915050565b611a416040805160a08101909152805f81526020015f81525f602082018190526040820181905260609091015290565b5f82815260016020819052604091829020825160a0810190935280549091839160ff1690811115611a7457611a746129a2565b6001811115611a8557611a856129a2565b81528154602090910190610100900460ff166002811115611aa857611aa86129a2565b6002811115611ab957611ab96129a2565b8152905463ffffffff62010000820481166020840152600160301b820481166040840152600160501b9091041660609091015292915050565b604051632246488d60e01b81523360048201525f907f000000000000000000000000cafea2c575550512582090aa06d0a069e7236b9e6001600160a01b031690632246488d90602401602060405180830381865afa158015611b56573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b7a9190612eec565b611b97576040516315c171d760e31b815260040160405180910390fd5b611be05f611ba5868861300d565b85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061244292505050565b95945050505050565b5f818152600160208190526040808320815160a08101909252805491929091839160ff90911690811115611c1f57611c1f6129a2565b6001811115611c3057611c306129a2565b81528154602090910190610100900460ff166002811115611c5357611c536129a2565b6002811115611c6457611c646129a2565b8152905463ffffffff62010000820481166020840152600160301b82048116604080850191909152600160501b909204811660609093019290925282015191925016611cc35760405163635e873760e01b815260040160405180910390fd5b600181602001516002811115611cdb57611cdb6129a2565b03611cf9576040516351618d5360e01b815260040160405180910390fd5b600281602001516002811115611d1157611d116129a2565b03611d2f576040516346c48e3760e11b815260040160405180910390fd5b5f8082516001811115611d4457611d446129a2565b1490508080611dd4575060405163288c314960e21b81523360048201527f000000000000000000000000cafea2c575550512582090aa06d0a069e7236b9e6001600160a01b03169063a230c52490602401602060405180830381865afa158015611db0573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611dd49190612eec565b611df15760405163148fe22160e11b815260040160405180910390fd5b801580611e7f5750604051632246488d60e01b81523360048201527f000000000000000000000000cafea2c575550512582090aa06d0a069e7236b9e6001600160a01b031690632246488d90602401602060405180830381865afa158015611e5b573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e7f9190612eec565b611e9c576040516315c171d760e31b815260040160405180910390fd5b816080015163ffffffff164211611ec65760405163f4a324ed60e01b815260040160405180910390fd5b5f83815260046020908152604091829020825160608101845281546001600160601b03808216808452600160601b90920481169483018590526001909301549092169381019390935210611f2d57604051630122f3c760e11b815260040160405180910390fd5b8115611f6757600381602001516001600160601b03161015611f62576040516314b8741160e11b815260040160405180910390fd5b612054565b5f6064600f7f0000000000000000000000005407381b6c251cfd498ccd4a1d877739cb7960b86001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611fc8573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fec9190612f3a565b611ff6919061313f565b6120009190613156565b90505f8260400151835f0151846020015161201b9190612f65565b6120259190612f65565b6001600160601b031690508181101561205157604051631f624c5160e01b815260040160405180910390fd5b50505b5f84815260036020908152604080832080548251818502810185019093528083529192909190849084015b8282101561216c575f848152602090819020604080516060810182526002860290920180546001600160a01b0381168452600160a01b90046001600160601b031693830193909352600183018054929392918401916120dd90612eb4565b80601f016020809104026020016040519081016040528092919081815260200182805461210990612eb4565b80156121545780601f1061212b57610100808354040283529160200191612154565b820191905f5260205f20905b81548152906001019060200180831161213757829003601f168201915b5050505050815250508152602001906001019061207f565b509293505f925050505b81518110156121f2576121ea82828151811061219457612194612f0b565b60200260200101515f01518383815181106121b1576121b1612f0b565b6020026020010151602001516001600160601b03168484815181106121d8576121d8612f0b565b602002602001015160400151846127eb565b600101612176565b50600160208581018290525f8781529082905260409020855181548793839160ff1916908381811115612227576122276129a2565b021790555060208201518154829061ff00191661010083600281111561224f5761224f6129a2565b02179055506040828101518254606085015160809095015169ffffffffffffffff0000199091166201000063ffffffff9384160263ffffffff60301b191617600160301b958316959095029490941763ffffffff60501b1916600160501b9190941602929092179055518581527f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f9060200160405180910390a15050505050565b5f5f7f0000000000000000000000005407381b6c251cfd498ccd4a1d877739cb7960b86001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561234e573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123729190612f3a565b604051632587701560e11b81526001600160a01b0385811660048301529192505f917f0000000000000000000000005407381b6c251cfd498ccd4a1d877739cb7960b81690634b0ee02a90602401602060405180830381865afa1580156123db573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906123ff9190612f3a565b61241190670de0b6b3a7640000612f84565b90505f606461242160058561313f565b61242b9190613156565b905080821161243a5781611be0565b949350505050565b5f5f6040518060a00160405280866001811115612461576124616129a2565b81526020015f8152602001612475426126f5565b63ffffffff1681526020016124906117556203f48042612f84565b63ffffffff1681526020016124b9620151806124af6203f48042612f84565b6117559190612f84565b63ffffffff1681525090505f5f81546124d190613175565b91829055505f81815260016020819052604090912083518154939550849391929091839160ff1990911690838181111561250d5761250d6129a2565b021790555060208201518154829061ff001916610100836002811115612535576125356129a2565b02179055506040828101518254606085015160809095015169ffffffffffffffff0000199091166201000063ffffffff9384160263ffffffff60301b191617600160301b958316959095029490941763ffffffff60501b1916600160501b91909416029290921790555f8381526002602052206125b284826131d9565b505f5b845181101561264a575f83815260036020526040902085518690839081106125df576125df612f0b565b6020908102919091018101518254600181810185555f948552938390208251938301516001600160601b0316600160a01b026001600160a01b039094169390931760029091029092019182556040810151909282019061263f90826131d9565b5050506001016125b5565b507f2d6a2a1a504050a1fa6107e44f49971fd89dbe544b433d65f1c572ce5fa3b7d182868560405161267e93929190613293565b60405180910390a1509392505050565b5f600160601b82106126f15760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201526536206269747360d01b60648201526084016119d1565b5090565b5f64010000000082106126f15760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b60648201526084016119d1565b5f61276442836132b8565b604051634c47e71d60e01b81526001600160a01b038581166004830152602482018390529192507f0000000000000000000000005407381b6c251cfd498ccd4a1d877739cb7960b890911690634c47e71d906044015f604051808303815f87803b1580156127d0575f5ffd5b505af11580156127e2573d5f5f3e3d5ffd5b50505050505050565b8151158061280257506001600160a01b0384163b15155b61281f57604051631d4ce23760e11b815260040160405180910390fd5b5f5f856001600160a01b0316858560405161283a91906132cb565b5f6040518083038185875af1925050503d805f8114612874576040519150601f19603f3d011682016040523d82523d5f602084013e612879565b606091505b5091509150811561288b5750506128b1565b80515f8190036119da5760405163f1a8c42d60e01b8152600481018590526024016119d1565b50505050565b5f602082840312156128c7575f5ffd5b5035919050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f82825180855260208501945060208160051b830101602085015f5b8381101561297d57848303601f19018852815180516001600160a01b031684526020808201516001600160601b031690850152604090810151606091850182905290612966908501826128ce565b6020998a0199909450929092019150600101612918565b50909695505050505050565b602081525f61299b60208301846128fc565b9392505050565b634e487b7160e01b5f52602160045260245ffd5b600281106129c6576129c66129a2565b9052565b600381106129da576129da6129a2565b50565b6129e88282516129b6565b60208101516129f6816129ca565b8060208401525063ffffffff604082015116604083015263ffffffff606082015116606083015263ffffffff60808201511660808301525050565b6001600160601b0381511682526001600160601b0360208201511660208301526001600160601b0360408201511660408301525050565b858152612a7860208201866129dd565b61016060c08201525f612a8f6101608301866128ce565b82810360e0840152612aa181866128fc565b915050611213610100830184612a31565b602081525f61299b60208301846128ce565b5f5f60408385031215612ad5575f5ffd5b50508035926020909101359150565b81516040820190612af4816129ca565b808352506001600160601b03602084015116602083015292915050565b60608101610cfa8284612a31565b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b0381118282101715612b5557612b55612b1f565b60405290565b604051606081016001600160401b0381118282101715612b5557612b55612b1f565b604051601f8201601f191681016001600160401b0381118282101715612ba557612ba5612b1f565b604052919050565b5f6001600160401b03821115612bc557612bc5612b1f565b5060051b60200190565b5f5f83601f840112612bdf575f5ffd5b5081356001600160401b03811115612bf5575f5ffd5b602083019150836020828501011115612c0c575f5ffd5b9250929050565b5f5f5f60408486031215612c25575f5ffd5b83356001600160401b03811115612c3a575f5ffd5b8401601f81018613612c4a575f5ffd5b8035612c5d612c5882612bad565b612b7d565b8082825260208201915060208360061b850101925088831115612c7e575f5ffd5b6020840193505b82841015612cc5576040848a031215612c9c575f5ffd5b612ca4612b33565b84358152602080860135818301529083526040909401939190910190612c85565b955050505060208401356001600160401b03811115612ce2575f5ffd5b612cee86828701612bcf565b9497909650939450505050565b5f5f60408385031215612d0c575f5ffd5b82359150602083013560038110612d21575f5ffd5b809150509250929050565b6001600160a01b03811681146129da575f5ffd5b5f60208284031215612d50575f5ffd5b813561299b81612d2c565b5f5f83601f840112612d6b575f5ffd5b5081356001600160401b03811115612d81575f5ffd5b6020830191508360208260051b8501011115612c0c575f5ffd5b5f5f60208385031215612dac575f5ffd5b82356001600160401b03811115612dc1575f5ffd5b612dcd85828601612d5b565b90969095509350505050565b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b82811015612e3057603f19878603018452612e1b8583516128ce565b94506020938401939190910190600101612dff565b50929695505050505050565b60a08101610cfa82846129dd565b5f5f5f5f60408587031215612e5d575f5ffd5b84356001600160401b03811115612e72575f5ffd5b612e7e87828801612d5b565b90955093505060208501356001600160401b03811115612e9c575f5ffd5b612ea887828801612bcf565b95989497509550505050565b600181811c90821680612ec857607f821691505b602082108103612ee657634e487b7160e01b5f52602260045260245ffd5b50919050565b5f60208284031215612efc575f5ffd5b8151801515811461299b575f5ffd5b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215612f2f575f5ffd5b815161299b81612d2c565b5f60208284031215612f4a575f5ffd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b6001600160601b038181168382160190811115610cfa57610cfa612f51565b80820180821115610cfa57610cfa612f51565b60408101612fa4846129ca565b9281526001600160601b039190911660209091015290565b5f5f8335601e19843603018112612fd1575f5ffd5b8301803591506001600160401b03821115612fea575f5ffd5b602001915036819003821315612c0c575f5ffd5b818382375f9101908152919050565b5f61301a612c5884612bad565b8381526020810190600585901b840136811115613035575f5ffd5b845b818110156131345780356001600160401b03811115613054575f5ffd5b86016060368290031215613066575f5ffd5b61306e612b5b565b813561307981612d2c565b815260208201356001600160601b0381168114613094575f5ffd5b602082015260408201356001600160401b038111156130b1575f5ffd5b919091019036601f8301126130c4575f5ffd5b81356001600160401b038111156130dd576130dd612b1f565b6130f0601f8201601f1916602001612b7d565b818152366020838601011115613104575f5ffd5b816020850160208301375f6020838301015280604084015250508086525050602084019350602081019050613037565b509095945050505050565b8082028115828204841417610cfa57610cfa612f51565b5f8261317057634e487b7160e01b5f52601260045260245ffd5b500490565b5f6001820161318657613186612f51565b5060010190565b601f8211156131d457805f5260205f20601f840160051c810160208510156131b25750805b601f840160051c820191505b818110156131d1575f81556001016131be565b50505b505050565b81516001600160401b038111156131f2576131f2612b1f565b613206816132008454612eb4565b8461318d565b6020601f821160018114613238575f83156132215750848201515b5f19600385901b1c1916600184901b1784556131d1565b5f84815260208120601f198516915b828110156132675787850151825560209485019460019092019101613247565b508482101561328457868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b8381526132a360208201846129b6565b606060408201525f611be060608301846128ce565b81810381811115610cfa57610cfa612f51565b5f82518060208501845e5f92019182525091905056fea264697066735822122073f38e1a03ae0d670896245f63507e4bd874a7bb1a2bc71557b51eb31888470564736f6c634300081c0033
Verified Source Code Full Match
Compiler: v0.8.28+commit.7893614a
EVM: prague
Optimization: Yes (200 runs)
Multicall.sol 35 lines
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.18;
abstract contract Multicall {
error RevertedWithoutReason(uint index);
// WARNING: Do not set this function as payable
function multicall(bytes[] calldata data) external returns (bytes[] memory results) {
uint callCount = data.length;
results = new bytes[](callCount);
for (uint i = 0; i < callCount; i++) {
(bool ok, bytes memory result) = address(this).delegatecall(data[i]);
if (!ok) {
uint length = result.length;
// 0 length returned from empty revert() / require(false)
if (length == 0) {
revert RevertedWithoutReason(i);
}
assembly {
revert(add(result, 0x20), length)
}
}
results[i] = result;
}
}
}
RegistryAware.sol 78 lines
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.28;
import "../interfaces/IRegistry.sol";
// contract indexes
uint constant C_REGISTRY = 1 << 0; // 1
uint constant C_GOVERNOR = 1 << 1; // 2
uint constant C_TOKEN = 1 << 2; // 4
uint constant C_TOKEN_CONTROLLER = 1 << 3; // 8
uint constant C_POOL = 1 << 4; // 16
uint constant C_COVER = 1 << 5; // 32
uint constant C_COVER_PRODUCTS = 1 << 6; // 64
uint constant C_STAKING_PRODUCTS = 1 << 7; // 128
uint constant C_RAMM = 1 << 8; // 256
uint constant C_SAFE_TRACKER = 1 << 9; // 512
uint constant C_LIMIT_ORDERS = 1 << 10; // 1024
uint constant C_STAKING_NFT = 1 << 11; // 2048
uint constant C_COVER_NFT = 1 << 12; // 4096
uint constant C_SWAP_OPERATOR = 1 << 13; // 8192
uint constant C_ASSESSMENTS = 1 << 14; // 16384
uint constant C_CLAIMS = 1 << 15; // 32768
uint constant C_STAKING_POOL_FACTORY = 1 << 16; // 65536
// pause types constants
uint constant PAUSE_GLOBAL = 1 << 0; // 1
uint constant PAUSE_RAMM = 1 << 1; // 2
uint constant PAUSE_SWAPS = 1 << 2; // 4
uint constant PAUSE_MEMBERSHIP = 1 << 3; // 8
uint constant PAUSE_ASSESSMENTS = 1 << 4; // 16
uint constant PAUSE_CLAIMS = 1 << 5; // 32
uint constant PAUSE_COVER = 1 << 6; // 64
contract RegistryAware {
IRegistry public immutable registry;
error Paused(uint currentState, uint checks);
error Unauthorized(address caller, uint callerIndex, uint authorizedBitmap);
error OnlyMember();
error OnlyAdvisoryBoard();
modifier whenNotPaused(uint mask) {
uint config = registry.getPauseConfig();
uint maskWithGlobal = mask | PAUSE_GLOBAL;
require(config & maskWithGlobal == 0, Paused(config, mask));
_;
}
modifier onlyContracts(uint authorizedBitmap) {
uint callerIndex = msg.sender == address(registry)
? C_REGISTRY
: registry.getContractIndexByAddress(msg.sender);
bool isAuthorized = callerIndex & authorizedBitmap != 0;
require(isAuthorized, Unauthorized(msg.sender, callerIndex, authorizedBitmap));
_;
}
modifier onlyAdvisoryBoard() {
require(registry.isAdvisoryBoardMember(msg.sender), OnlyAdvisoryBoard());
_;
}
modifier onlyMember() {
require(registry.isMember(msg.sender), OnlyMember());
_;
}
function fetch(uint index) internal view returns (address) {
return registry.getContractAddressByIndex(index);
}
constructor(address _registry) {
registry = IRegistry(_registry);
}
}
IGovernor.sol 104 lines
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >=0.5.0;
interface IGovernor {
enum ProposalKind {
AdvisoryBoard,
Member
}
enum Choice {
Against,
For,
Abstain
}
enum ProposalStatus {
Proposed,
Executed,
Canceled
}
struct Proposal { // 112 bits
ProposalKind kind;
ProposalStatus status;
uint32 proposedAt;
uint32 voteBefore;
uint32 executeAfter;
}
struct Transaction {
address target;
uint96 value;
bytes data;
}
struct Vote {
Choice choice;
uint96 weight;
}
struct Tally {
uint96 againstVotes;
uint96 forVotes;
uint96 abstainVotes;
}
struct AdvisoryBoardSwap {
uint from; // memberId
uint to; // memberId
}
function propose(Transaction[] calldata transactions, string calldata description) external returns (uint proposalId);
function execute(uint proposalId) external payable;
function getVoteWeight(address voter) external view returns (uint);
function getProposal(uint proposalId) external view returns (Proposal memory);
function getProposalDescription(uint proposalId) external view returns (string memory);
function getProposalTransactions(uint proposalId) external view returns (Transaction[] memory);
function getProposalTally(uint proposalId) external view returns (Tally memory);
function getProposalWithDetails(uint _proposalId) external view returns (
uint proposalId,
Proposal memory,
string memory,
Transaction[] memory,
Tally memory
);
function getVote(uint proposalId, uint memberId) external view returns (Vote memory);
event ProposalExecuted(uint proposalId);
event VoteCast(uint indexed proposalId, ProposalKind indexed kind, uint indexed voterId, Choice choice, uint weight);
event ProposalCanceled(uint proposalId);
event ProposalCreated(uint proposalId, ProposalKind kind, string description);
error InvalidAdvisoryBoardSwap();
error AlreadyAdvisoryBoardMember();
error OnlyAdvisoryBoardMember();
error OnlyGovernor();
error NotMember();
error NotAuthorizedToVote();
error ProposalNotFound();
error ProposalAlreadyExecuted();
error ProposalIsCanceled();
// voting
error VotePeriodHasEnded();
error VoteTalliedAgainst();
error VoteThresholdNotMet();
error VoteQuorumNotMet();
error ProposalThresholdNotMet();
error AlreadyVoted();
// cancellation
error CannotCancelMemberProposal();
// execution
error ExecutionPeriodHasEnded();
error TimelockHasNotEnded();
error TargetIsNotAContract();
}
INXMToken.sol 95 lines
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >=0.5.0;
interface INXMToken {
function burn(uint256 amount) external returns (bool);
function burnFrom(address from, uint256 value) external returns (bool);
function operatorTransfer(address from, uint256 value) external returns (bool);
function mint(address account, uint256 amount) external;
function isLockedForMV(address member) external view returns (uint);
function whiteListed(address member) external view returns (bool);
function addToWhiteList(address _member) external returns (bool);
function removeFromWhiteList(address _member) external returns (bool);
function changeOperator(address _newOperator) external returns (bool);
function lockForMemberVote(address _of, uint _days) external;
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) 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 `amount` 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 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
/**
* @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);
}
IRegistry.sol 111 lines
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >=0.8.0;
interface IRegistry {
struct Contract {
address addr;
bool isProxy;
}
struct SystemPause {
uint48 config;
uint48 proposedConfig;
address proposer;
}
struct MembersMeta {
uint48 memberCount;
uint48 lastMemberId;
address kycAuthAddress;
}
/* == EMERGENCY PAUSE == */
function setEmergencyAdmin(address _emergencyAdmin, bool enabled) external;
function proposePauseConfig(uint config) external;
function confirmPauseConfig(uint config) external;
function getSystemPause() external view returns (SystemPause memory);
function getPauseConfig() external view returns (uint config);
function isPaused(uint mask) external view returns (bool);
function isEmergencyAdmin(address member) external view returns (bool);
/* == MEMBERSHIP MANAGEMENT == */
function isMember(address member) external view returns (bool);
function getMemberId(address member) external view returns (uint);
function getMemberAddress(uint memberId) external view returns (address);
function getMemberCount() external view returns (uint);
function getLastMemberId() external view returns (uint);
function join(address member, bytes memory signature) external payable;
function switchTo(address to) external;
function switchFor(address from, address to) external;
function leave() external;
function setKycAuthAddress(address kycAuthAddress) external;
function getKycAuthAddress() external view returns (address);
/* == ADVISORY BOARD MANAGEMENT == */
function isAdvisoryBoardMember(address member) external view returns (bool);
function isAdvisoryBoardMemberById(uint memberId) external view returns (bool);
function getAdvisoryBoardSeat(address member) external view returns (uint);
function getMemberAddressBySeat(uint seat) external view returns (address);
function swapAdvisoryBoardMember(uint from, uint to) external;
/* == CONTRACT MANAGEMENT == */
function isValidContractIndex(uint index) external pure returns (bool);
function isProxyContract(uint index) external view returns (bool);
function getContractAddressByIndex(uint index) external view returns (address payable);
function getContractIndexByAddress(address contractAddress) external view returns (uint);
function getContracts(uint[] memory indexes) external view returns (Contract[] memory);
function deployContract(uint index, bytes32 salt, address implementation) external;
function addContract(uint index, address contractAddress, bool isProxy) external;
function upgradeContract(uint index, address implementation) external;
function removeContract(uint index) external;
/* == MIGRATIONS == */
function migrateMembers(address[] calldata membersToMigrate) external;
function migrateAdvisoryBoardMembers(address[] calldata abMembers) external;
// joined: MembershipChanged(memberId, address(0), current)
// swapped: MembershipChanged(memberId, previous, current)
// left: MembershipChanged(memberId, current, address(0))
event MembershipChanged(uint indexed memberId, address indexed previous, address indexed current);
event AdvisoryBoardMemberSwapped(uint indexed seat, uint indexed from, uint indexed to);
event ContractDeployed(uint indexed index, address indexed proxy, address implementation);
event ContractUpgraded(uint indexed index, address indexed proxy, address implementation);
event ContractAdded(uint indexed index, address indexed contractAddress, bool isProxy);
event ContractRemoved(uint indexed index, address indexed contractAddress, bool isProxy);
event EmergencyAdminSet(address indexed emergencyAdmin, bool enabled);
event PauseConfigProposed(uint config, address indexed proposer);
event PauseConfigConfirmed(uint config, address indexed confirmer);
error ContractAlreadyExists();
error InvalidContractIndex();
error InvalidContractAddress();
error ContractDoesNotExist();
error ContractIsNotProxy();
error OnlyEmergencyAdmin();
error ProposerCannotConfirmPause();
error PauseConfigMismatch();
error NoConfigProposed();
error Paused(uint currentState, uint checks);
error NotMember();
error AlreadyMember();
error AddressAlreadyUsedForJoining();
error InvalidJoinFee();
error InvalidSignature();
error FeeTransferFailed();
error NotAdvisoryBoardMember();
error AlreadyAdvisoryBoardMember();
error AdvisoryBoardMemberCannotLeave();
error InvalidSeat();
error OnlyGovernor();
error NotProxyOwner();
error NotMemberRoles();
}
ITokenController.sol 99 lines
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >=0.5.0;
import "./INXMToken.sol";
interface ITokenController {
struct StakingPoolNXMBalances {
uint128 rewards;
uint128 deposits;
}
struct StakingPoolOwnershipOffer {
address proposedManager;
uint96 deadline;
}
struct WithdrawAssessment {
bool stake;
bool rewards;
}
/// @notice The stake deposit / rewards in a staking pool that will be withdrawn.
/// @dev Call StakingViewer.getToken to get tokenId / trancheId information
/// @param tokenId The ID of the token stake deposit / rewards that will be withrawn.
/// @param trancheIds An array of tranche IDs representing the tranches where the stake was deposited.
struct StakingPoolDeposit {
uint tokenId;
uint[] trancheIds;
}
/// @notice Represents the rewards distributed to a staking pool manager.
/// @dev Call StakingViewer.getManagerTokenRewardsByAddr to get poolId / trancheId information
/// @param poolId The ID of the pool managed by the manager.
/// @param trancheIds An array of tranche IDs representing the tranches where the manager rewards were distributed.
struct StakingPoolManagerReward {
uint poolId;
uint[] trancheIds;
}
/* ========== VIEWS ========== */
function token() external view returns (INXMToken);
function totalSupply() external view returns (uint);
function totalBalanceOf(address _of) external view returns (uint amount);
function totalBalanceOfWithoutDelegations(address _of) external view returns (uint amount);
function getTokenPrice() external view returns (uint tokenPrice);
function getStakingPoolManager(uint poolId) external view returns (address manager);
function getManagerStakingPools(address manager) external view returns (uint[] memory poolIds);
function isStakingPoolManager(address member) external view returns (bool);
function getStakingPoolOwnershipOffer(uint poolId) external view returns (address proposedManager, uint deadline);
function stakingPoolNXMBalances(uint poolId) external view returns (uint128 rewards, uint128 deposits);
/* ========== MUTATIVE FUNCTIONS ========== */
function changeOperator(address _newOperator) external;
function operatorTransfer(address _from, address _to, uint _value) external returns (bool);
function burnFrom(address _of, uint amount) external returns (bool);
function addToWhitelist(address _member) external;
function removeFromWhitelist(address _member) external;
function switchMembership(address from, address to, bool includeNxmTokens) external;
function mint(address _member, uint _amount) external;
function lockForMemberVote(address _of, uint _days) external;
function assignStakingPoolManager(uint poolId, address manager) external;
function createStakingPoolOwnershipOffer(uint poolId, address proposedManager, uint deadline) external;
function acceptStakingPoolOwnershipOffer(uint poolId) external;
function cancelStakingPoolOwnershipOffer(uint poolId) external;
function mintStakingPoolNXMRewards(uint amount, uint poolId) external;
function burnStakingPoolNXMRewards(uint amount, uint poolId) external;
function depositStakedNXM(address from, uint amount, uint poolId) external;
function withdrawNXMStakeAndRewards(address to, uint stakeToWithdraw, uint rewardsToWithdraw, uint poolId) external;
function burnStakedNXM(uint amount, uint poolId) external;
}
SafeUintCast.sol 467 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
/**
* @dev Wrappers over Solidity's uintXX casting operators with added overflow
* checks.
*
* Downcasting from uint256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` restores this intuition by
* reverting the transaction when such an operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeUintCast {
/**
* @dev Returns the downcasted uint248 from uint256, reverting on
* overflow (when the input is greater than largest uint248).
*
* Counterpart to Solidity's `uint248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toUint248(uint256 value) internal pure returns (uint248) {
require(value < 2**248, "SafeCast: value doesn\'t fit in 248 bits");
return uint248(value);
}
/**
* @dev Returns the downcasted uint240 from uint256, reverting on
* overflow (when the input is greater than largest uint240).
*
* Counterpart to Solidity's `uint240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toUint240(uint256 value) internal pure returns (uint240) {
require(value < 2**240, "SafeCast: value doesn\'t fit in 240 bits");
return uint240(value);
}
/**
* @dev Returns the downcasted uint232 from uint256, reverting on
* overflow (when the input is greater than largest uint232).
*
* Counterpart to Solidity's `uint232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toUint232(uint256 value) internal pure returns (uint232) {
require(value < 2**232, "SafeCast: value doesn\'t fit in 232 bits");
return uint232(value);
}
/**
* @dev Returns the downcasted uint224 from uint256, reverting on
* overflow (when the input is greater than largest uint224).
*
* Counterpart to Solidity's `uint224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toUint224(uint256 value) internal pure returns (uint224) {
require(value < 2**224, "SafeCast: value doesn\'t fit in 224 bits");
return uint224(value);
}
/**
* @dev Returns the downcasted uint216 from uint256, reverting on
* overflow (when the input is greater than largest uint216).
*
* Counterpart to Solidity's `uint216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toUint216(uint256 value) internal pure returns (uint216) {
require(value < 2**216, "SafeCast: value doesn\'t fit in 216 bits");
return uint216(value);
}
/**
* @dev Returns the downcasted uint208 from uint256, reverting on
* overflow (when the input is greater than largest uint208).
*
* Counterpart to Solidity's `uint208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toUint208(uint256 value) internal pure returns (uint208) {
require(value < 2**208, "SafeCast: value doesn\'t fit in 208 bits");
return uint208(value);
}
/**
* @dev Returns the downcasted uint200 from uint256, reverting on
* overflow (when the input is greater than largest uint200).
*
* Counterpart to Solidity's `uint200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toUint200(uint256 value) internal pure returns (uint200) {
require(value < 2**200, "SafeCast: value doesn\'t fit in 200 bits");
return uint200(value);
}
/**
* @dev Returns the downcasted uint192 from uint256, reverting on
* overflow (when the input is greater than largest uint192).
*
* Counterpart to Solidity's `uint192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toUint192(uint256 value) internal pure returns (uint192) {
require(value < 2**192, "SafeCast: value doesn\'t fit in 192 bits");
return uint192(value);
}
/**
* @dev Returns the downcasted uint184 from uint256, reverting on
* overflow (when the input is greater than largest uint184).
*
* Counterpart to Solidity's `uint184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toUint184(uint256 value) internal pure returns (uint184) {
require(value < 2**184, "SafeCast: value doesn\'t fit in 184 bits");
return uint184(value);
}
/**
* @dev Returns the downcasted uint176 from uint256, reverting on
* overflow (when the input is greater than largest uint176).
*
* Counterpart to Solidity's `uint176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toUint176(uint256 value) internal pure returns (uint176) {
require(value < 2**176, "SafeCast: value doesn\'t fit in 176 bits");
return uint176(value);
}
/**
* @dev Returns the downcasted uint168 from uint256, reverting on
* overflow (when the input is greater than largest uint168).
*
* Counterpart to Solidity's `uint168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toUint168(uint256 value) internal pure returns (uint168) {
require(value < 2**168, "SafeCast: value doesn\'t fit in 168 bits");
return uint168(value);
}
/**
* @dev Returns the downcasted uint160 from uint256, reverting on
* overflow (when the input is greater than largest uint160).
*
* Counterpart to Solidity's `uint160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toUint160(uint256 value) internal pure returns (uint160) {
require(value < 2**160, "SafeCast: value doesn\'t fit in 160 bits");
return uint160(value);
}
/**
* @dev Returns the downcasted uint152 from uint256, reverting on
* overflow (when the input is greater than largest uint152).
*
* Counterpart to Solidity's `uint152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toUint152(uint256 value) internal pure returns (uint152) {
require(value < 2**152, "SafeCast: value doesn\'t fit in 152 bits");
return uint152(value);
}
/**
* @dev Returns the downcasted uint144 from uint256, reverting on
* overflow (when the input is greater than largest uint144).
*
* Counterpart to Solidity's `uint144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toUint144(uint256 value) internal pure returns (uint144) {
require(value < 2**144, "SafeCast: value doesn\'t fit in 144 bits");
return uint144(value);
}
/**
* @dev Returns the downcasted uint136 from uint256, reverting on
* overflow (when the input is greater than largest uint136).
*
* Counterpart to Solidity's `uint136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toUint136(uint256 value) internal pure returns (uint136) {
require(value < 2**136, "SafeCast: value doesn\'t fit in 136 bits");
return uint136(value);
}
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toUint128(uint256 value) internal pure returns (uint128) {
require(value < 2**128, "SafeCast: value doesn\'t fit in 128 bits");
return uint128(value);
}
/**
* @dev Returns the downcasted uint120 from uint256, reverting on
* overflow (when the input is greater than largest uint120).
*
* Counterpart to Solidity's `uint120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toUint120(uint256 value) internal pure returns (uint120) {
require(value < 2**120, "SafeCast: value doesn\'t fit in 120 bits");
return uint120(value);
}
/**
* @dev Returns the downcasted uint112 from uint256, reverting on
* overflow (when the input is greater than largest uint112).
*
* Counterpart to Solidity's `uint112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toUint112(uint256 value) internal pure returns (uint112) {
require(value < 2**112, "SafeCast: value doesn\'t fit in 112 bits");
return uint112(value);
}
/**
* @dev Returns the downcasted uint104 from uint256, reverting on
* overflow (when the input is greater than largest uint104).
*
* Counterpart to Solidity's `uint104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toUint104(uint256 value) internal pure returns (uint104) {
require(value < 2**104, "SafeCast: value doesn\'t fit in 104 bits");
return uint104(value);
}
/**
* @dev Returns the downcasted uint96 from uint256, reverting on
* overflow (when the input is greater than largest uint96).
*
* Counterpart to Solidity's `uint104` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toUint96(uint256 value) internal pure returns (uint96) {
require(value < 2**96, "SafeCast: value doesn\'t fit in 96 bits");
return uint96(value);
}
/**
* @dev Returns the downcasted uint88 from uint256, reverting on
* overflow (when the input is greater than largest uint88).
*
* Counterpart to Solidity's `uint104` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toUint88(uint256 value) internal pure returns (uint88) {
require(value < 2**88, "SafeCast: value doesn\'t fit in 88 bits");
return uint88(value);
}
/**
* @dev Returns the downcasted uint80 from uint256, reverting on
* overflow (when the input is greater than largest uint80).
*
* Counterpart to Solidity's `uint104` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toUint80(uint256 value) internal pure returns (uint80) {
require(value < 2**80, "SafeCast: value doesn\'t fit in 80 bits");
return uint80(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toUint64(uint256 value) internal pure returns (uint64) {
require(value < 2**64, "SafeCast: value doesn\'t fit in 64 bits");
return uint64(value);
}
/**
* @dev Returns the downcasted uint56 from uint256, reverting on
* overflow (when the input is greater than largest uint56).
*
* Counterpart to Solidity's `uint56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toUint56(uint256 value) internal pure returns (uint56) {
require(value < 2**56, "SafeCast: value doesn\'t fit in 56 bits");
return uint56(value);
}
/**
* @dev Returns the downcasted uint48 from uint256, reverting on
* overflow (when the input is greater than largest uint48).
*
* Counterpart to Solidity's `uint48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toUint48(uint256 value) internal pure returns (uint48) {
require(value < 2**48, "SafeCast: value doesn\'t fit in 48 bits");
return uint48(value);
}
/**
* @dev Returns the downcasted uint40 from uint256, reverting on
* overflow (when the input is greater than largest uint40).
*
* Counterpart to Solidity's `uint40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toUint40(uint256 value) internal pure returns (uint40) {
require(value < 2**40, "SafeCast: value doesn\'t fit in 40 bits");
return uint40(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toUint32(uint256 value) internal pure returns (uint32) {
require(value < 2**32, "SafeCast: value doesn\'t fit in 32 bits");
return uint32(value);
}
/**
* @dev Returns the downcasted uint24 from uint256, reverting on
* overflow (when the input is greater than largest uint24).
*
* Counterpart to Solidity's `uint24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toUint24(uint256 value) internal pure returns (uint24) {
require(value < 2**24, "SafeCast: value doesn\'t fit in 24 bits");
return uint24(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toUint16(uint256 value) internal pure returns (uint16) {
require(value < 2**16, "SafeCast: value doesn\'t fit in 16 bits");
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits.
*/
function toUint8(uint256 value) internal pure returns (uint8) {
require(value < 2**8, "SafeCast: value doesn\'t fit in 8 bits");
return uint8(value);
}
}
Governor.sol 283 lines
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.28;
import "../../abstract/Multicall.sol";
import "../../abstract/RegistryAware.sol";
import "../../interfaces/IGovernor.sol";
import "../../interfaces/IRegistry.sol";
import "../../interfaces/ITokenController.sol";
import "../../libraries/SafeUintCast.sol";
contract Governor is IGovernor, RegistryAware, Multicall {
using SafeUintCast for uint;
/* ========== storage ========== */
uint public proposalCount;
mapping(uint proposalId => Proposal) internal proposals;
mapping(uint proposalId => string) internal descriptions;
mapping(uint proposalId => Transaction[]) internal transactions;
mapping(uint proposalId => Tally) internal tallies;
mapping(uint proposalId => mapping(uint memberId => Vote)) internal votes;
/* ========== immutables and constants ========== */
ITokenController public immutable tokenController;
uint public constant TIMELOCK_PERIOD = 1 days;
uint public constant VOTING_PERIOD = 3 days;
uint public constant ADVISORY_BOARD_THRESHOLD = 3;
uint public constant MEMBER_VOTE_QUORUM_PERCENTAGE = 15; // 15% of token supply
uint public constant PROPOSAL_THRESHOLD = 100 ether; // minimum 100 tokens to open an AB swap proposal
uint public constant VOTE_WEIGHT_CAP_PERCENTAGE = 5; // 5%
/* ========== logic ========== */
constructor(address _registry) RegistryAware(_registry) {
tokenController = ITokenController(fetch(C_TOKEN_CONTROLLER));
}
function getVoteWeight(address voter) public view returns (uint) {
return registry.isMember(voter) ? _getVoteWeight(voter) : 0;
}
function _getVoteWeight(address voter) internal view returns (uint) {
uint totalSupply = tokenController.totalSupply();
uint weight = tokenController.totalBalanceOf(voter) + 1 ether;
uint maxWeight = totalSupply * VOTE_WEIGHT_CAP_PERCENTAGE / 100;
return weight > maxWeight ? maxWeight : weight;
}
function _lockTokenTransfers(address voter, uint deadline) internal {
uint duration = deadline - block.timestamp;
tokenController.lockForMemberVote(voter, duration);
}
function propose(
Transaction[] calldata txs,
string calldata description
) external returns (uint proposalId) {
require(registry.isAdvisoryBoardMember(msg.sender), OnlyAdvisoryBoardMember());
return _propose(ProposalKind.AdvisoryBoard, txs, description);
}
function proposeAdvisoryBoardSwap(
AdvisoryBoardSwap[] memory swaps,
string calldata description
) external returns (uint proposalId) {
require(registry.isMember(msg.sender), NotMember());
// prevent spam
uint weight = _getVoteWeight(msg.sender);
require(weight > PROPOSAL_THRESHOLD, ProposalThresholdNotMet());
Transaction[] memory txs = new Transaction[](swaps.length);
for (uint i = 0; i < swaps.length; i++) {
require(swaps[i].from != swaps[i].to, InvalidAdvisoryBoardSwap());
require(swaps[i].from != 0 && swaps[i].to != 0, InvalidAdvisoryBoardSwap());
require(registry.isAdvisoryBoardMemberById(swaps[i].from), InvalidAdvisoryBoardSwap());
require(registry.getMemberAddress(swaps[i].to) != address(0), NotMember());
txs[i] = Transaction({
target: address(registry),
value: 0,
data: abi.encodeWithSelector(registry.swapAdvisoryBoardMember.selector, swaps[i].from, swaps[i].to)
});
}
return _propose(ProposalKind.Member, txs, description);
}
function _propose(
ProposalKind kind,
Transaction[] memory txs,
string memory description
) internal returns (uint proposalId) {
Proposal memory proposal = Proposal({
kind: kind,
proposedAt: block.timestamp.toUint32(),
voteBefore: (block.timestamp + VOTING_PERIOD).toUint32(),
executeAfter: (block.timestamp + VOTING_PERIOD + TIMELOCK_PERIOD).toUint32(),
status: ProposalStatus.Proposed
});
proposalId = ++proposalCount;
proposals[proposalId] = proposal;
descriptions[proposalId] = description;
for (uint i = 0; i < txs.length; i++) {
transactions[proposalId].push(txs[i]);
}
emit ProposalCreated(proposalId, kind, description);
return proposalId;
}
function cancel(uint proposalId) external {
require(registry.isAdvisoryBoardMember(msg.sender), OnlyAdvisoryBoardMember());
Proposal memory proposal = proposals[proposalId];
require(proposal.proposedAt > 0, ProposalNotFound());
require(proposal.kind == ProposalKind.AdvisoryBoard, CannotCancelMemberProposal());
require(proposal.status != ProposalStatus.Executed, ProposalAlreadyExecuted());
require(proposal.status != ProposalStatus.Canceled, ProposalIsCanceled());
proposal.status = ProposalStatus.Canceled;
proposals[proposalId] = proposal;
emit ProposalCanceled(proposalId);
}
function vote(uint proposalId, Choice choice) external {
Proposal memory proposal = proposals[proposalId];
require(proposal.proposedAt > 0, ProposalNotFound());
require(block.timestamp < proposal.voteBefore, VotePeriodHasEnded());
require(proposal.status != ProposalStatus.Executed, ProposalAlreadyExecuted());
require(proposal.status != ProposalStatus.Canceled, ProposalIsCanceled());
uint memberId = registry.getMemberId(msg.sender);
require(memberId > 0, NotMember());
bool isAbProposal = proposal.kind == ProposalKind.AdvisoryBoard;
uint voterId = isAbProposal
? registry.getAdvisoryBoardSeat(msg.sender)
: memberId;
require(votes[proposalId][voterId].weight == 0, AlreadyVoted());
uint96 weight = (isAbProposal ? 1 : _getVoteWeight(msg.sender)).toUint96();
votes[proposalId][voterId] = Vote({ choice: choice, weight: weight });
if (choice == Choice.For) {
tallies[proposalId].forVotes += weight;
}
if (choice == Choice.Against) {
tallies[proposalId].againstVotes += weight;
}
if (choice == Choice.Abstain) {
tallies[proposalId].abstainVotes += weight;
}
if (isAbProposal && tallies[proposalId].forVotes >= ADVISORY_BOARD_THRESHOLD) {
// start the timelock if the AB proposal has met the threshold
proposal.executeAfter = (block.timestamp + TIMELOCK_PERIOD).toUint32();
proposals[proposalId].executeAfter = proposal.executeAfter;
proposals[proposalId].voteBefore = block.timestamp.toUint32();
}
if(!isAbProposal) {
_lockTokenTransfers(msg.sender, proposal.executeAfter);
}
emit VoteCast(proposalId, proposal.kind, voterId, choice, weight);
}
function _performCall(address target, uint value, bytes memory data, uint txIndex) internal {
// if data is not empty - the target is assumed to be a contract
require(data.length == 0 || target.code.length != 0, TargetIsNotAContract());
(bool ok, bytes memory returndata) = target.call{value: value}(data);
if (ok) {
return;
}
uint size = returndata.length;
if (size == 0) {
revert RevertedWithoutReason(txIndex);
}
// bubble up the revert reason
assembly {
revert(add(returndata, 0x20), size)
}
}
function execute(uint proposalId) external payable {
Proposal memory proposal = proposals[proposalId];
require(proposal.proposedAt > 0, ProposalNotFound());
require(proposal.status != ProposalStatus.Executed, ProposalAlreadyExecuted());
require(proposal.status != ProposalStatus.Canceled, ProposalIsCanceled());
bool isAbProposal = proposal.kind == ProposalKind.AdvisoryBoard;
require(isAbProposal || registry.isMember(msg.sender), NotMember());
require(!isAbProposal || registry.isAdvisoryBoardMember(msg.sender), OnlyAdvisoryBoardMember());
require(block.timestamp > proposal.executeAfter, TimelockHasNotEnded());
Tally memory tally = tallies[proposalId];
require(tally.forVotes > tally.againstVotes, VoteTalliedAgainst());
if (isAbProposal) {
require(tally.forVotes >= ADVISORY_BOARD_THRESHOLD, VoteThresholdNotMet());
} else {
uint quorum = tokenController.totalSupply() * MEMBER_VOTE_QUORUM_PERCENTAGE / 100;
uint totalVotes = tally.forVotes + tally.againstVotes + tally.abstainVotes;
require(totalVotes >= quorum, VoteQuorumNotMet());
}
Transaction[] memory txs = transactions[proposalId];
for (uint i = 0; i < txs.length; i++) {
_performCall(txs[i].target, txs[i].value, txs[i].data, i);
}
proposal.status = ProposalStatus.Executed;
proposals[proposalId] = proposal;
emit ProposalExecuted(proposalId);
}
function getProposal(uint proposalId) external view returns (Proposal memory) {
return proposals[proposalId];
}
function getProposalDescription(uint proposalId) external view returns (string memory) {
return descriptions[proposalId];
}
function getProposalTransactions(uint proposalId) external view returns (Transaction[] memory) {
return transactions[proposalId];
}
function getProposalTally(uint proposalId) external view returns (Tally memory) {
return tallies[proposalId];
}
function getProposalWithDetails(uint _proposalId) external view returns (
uint proposalId,
Proposal memory,
string memory,
Transaction[] memory,
Tally memory
) {
return (
_proposalId,
proposals[_proposalId],
descriptions[_proposalId],
transactions[_proposalId],
tallies[_proposalId]
);
}
function getVote(uint proposalId, uint memberId) external view returns (Vote memory) {
return votes[proposalId][memberId];
}
}
Read Contract
ADVISORY_BOARD_THRESHOLD 0x92be0d83 → uint256
MEMBER_VOTE_QUORUM_PERCENTAGE 0x6d444362 → uint256
PROPOSAL_THRESHOLD 0xa6c26603 → uint256
TIMELOCK_PERIOD 0x4a5bcbf8 → uint256
VOTE_WEIGHT_CAP_PERCENTAGE 0x37bfaa1b → uint256
VOTING_PERIOD 0xb1610d7e → uint256
getProposal 0xc7f758a8 → tuple
getProposalDescription 0x229acb17 → string
getProposalTally 0x8341d6ef → tuple
getProposalTransactions 0x00a6e74b → tuple[]
getProposalWithDetails 0x1780a651 → uint256, tuple, string, tuple[], tuple
getVote 0x49330cb8 → tuple
getVoteWeight 0xa730117e → uint256
proposalCount 0xda35c664 → uint256
registry 0x7b103999 → address
tokenController 0xeddd9d82 → address
Write Contract 6 functions
These functions modify contract state and require a wallet transaction to execute.
cancel 0x40e58ee5
uint256 proposalId
execute 0xfe0d94c1
uint256 proposalId
multicall 0xac9650d8
bytes[] data
returns: bytes[]
propose 0x0e30b531
tuple[] txs
string description
returns: uint256
proposeAdvisoryBoardSwap 0x28061d5c
tuple[] swaps
string description
returns: uint256
vote 0x943e8216
uint256 proposalId
uint8 choice
Recent Transactions
This address has 1 on-chain transactions, but only 1.4% of the chain is indexed. Transactions will appear as indexing progresses. View on Etherscan →