Cryo Explorer Ethereum Mainnet

Address Contract Partially Verified

Address 0x2234a7c690AF5de948B3a1CcbEa43705E4583D2d
Balance 0 ETH
Nonce 1
Code Size 14622 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

14622 bytes
0x608060405234801561001057600080fd5b50600436106101c45760003560e01c806386bfdb19116100f9578063d27761ef11610097578063ec16bf4711610071578063ec16bf47146104f6578063ee5b11c314610512578063f2fde38b14610542578063f7f2e80d1461055e576101c4565b8063d27761ef1461048e578063e390ddde146104be578063ec06a89a146104da576101c4565b80638da5cb5b116100d35780638da5cb5b14610403578063ae49945d14610421578063b61d27f61461043f578063b754021914610470576101c4565b806386bfdb191461039857806388660611146103cb5780638980f11f146103e7576101c4565b806370c8f7fe1161016657806381d81d2a1161014057806381d81d2a1461030057806381d8b3f81461033057806382eac7f01461034c578063843d96f21461037c576101c4565b806370c8f7fe146102a7578063715018a6146102c35780637c43215f146102cd576101c4565b806320263e87116101a257806320263e87146102355780632f1d5a601461025357806345c126261461026f57806360976e6f1461028b576101c4565b806303ea9f1f146101c95780630f37b6ba146101f9578063127effb214610217575b600080fd5b6101e360048036038101906101de9190612abf565b61057a565b6040516101f09190612b05565b60405180910390f35b610201610592565b60405161020e9190612b05565b60405180910390f35b61021f6106ab565b60405161022c9190612b2f565b60405180910390f35b61023d6106d1565b60405161024a9190612b2f565b60405180910390f35b61026d60048036038101906102689190612abf565b6106f7565b005b61028960048036038101906102849190612b76565b61079e565b005b6102a560048036038101906102a09190612bb6565b610e3f565b005b6102c160048036038101906102bc9190612b76565b610e51565b005b6102cb610ff2565b005b6102e760048036038101906102e29190612abf565b611006565b6040516102f79493929190612bfe565b60405180910390f35b61031a60048036038101906103159190612abf565b61113e565b6040516103279190612b05565b60405180910390f35b61034a60048036038101906103459190612c6f565b6111e8565b005b61036660048036038101906103619190612bb6565b611501565b6040516103739190612b2f565b60405180910390f35b61039660048036038101906103919190612caf565b611540565b005b6103b260048036038101906103ad9190612abf565b611b63565b6040516103c29493929190612d2a565b60405180910390f35b6103e560048036038101906103e09190612d6f565b611ce4565b005b61040160048036038101906103fc9190612b76565b611e9b565b005b61040b611eb2565b6040516104189190612b2f565b60405180910390f35b610429611edb565b6040516104369190612b2f565b60405180910390f35b61045960048036038101906104549190612e14565b611f01565b604051610467929190612f18565b60405180910390f35b610478611f90565b6040516104859190612b05565b60405180910390f35b6104a860048036038101906104a39190612abf565b611f96565b6040516104b59190612f48565b60405180910390f35b6104d860048036038101906104d39190612abf565b611fb6565b005b6104f460048036038101906104ef9190612c6f565b612128565b005b610510600480360381019061050b9190612f63565b612433565b005b61052c60048036038101906105279190612abf565b61262e565b6040516105399190612f48565b60405180910390f35b61055c60048036038101906105579190612abf565b61264e565b005b61057860048036038101906105739190612fb6565b6126d1565b005b60086020528060005260406000206000915090505481565b6000806000905060005b6004805490508110156106a35760066000600483815481106105c1576105c0613009565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050160009054906101000a900460ff16610690576106826004828154811061065257610651613009565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1661113e565b8261068d9190613067565b91505b808061069b9061309b565b91505061059c565b508091505090565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6106ff6127d7565b7f2709918445f306d3e94d280907c62c5d2525ac3192d2e544774c7f181d65af3e600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16826040516107529291906130e3565b60405180910390a180600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b81600560008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1680156108455750600660008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050160009054906101000a900460ff16155b610884576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161087b90613169565b60405180910390fd5b6009546108908261113e565b116108d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108c7906131d5565b60405180910390fd5b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061095e575061092f611eb2565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b61099d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161099490613241565b60405180910390fd5b6000600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff1663095ea7b3600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16856040518363ffffffff1660e01b8152600401610a61929190613261565b6020604051808303816000875af1158015610a80573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aa4919061329f565b506000600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1685600660008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600660008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16600660008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206004015489604051602401610c63969594939291906132cc565b6040516020818303038152906040527fb649fbf4000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051610ced9190613369565b600060405180830381855af49150503d8060008114610d28576040519150601f19603f3d011682016040523d82523d6000602084013e610d2d565b606091505b5050905080610d71576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d68906133cc565b60405180910390fd5b42600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206006018190555083600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600701819055507ff17784554852232b03320852ce4646e3da26e60c45891d2364716686a80a41048585604051610e30929190613261565b60405180910390a15050505050565b610e476127d7565b8060098190555050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480610edf5750610eb0611eb2565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b610f1e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610f1590613241565b60405180910390fd5b6000610f298361113e565b90506000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f9a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fbe9190613425565b600a610fca9190613585565b8284610fd691906135d0565b610fe09190613641565b9050610fec848261079e565b50505050565b610ffa6127d7565b6110046000612855565b565b600080600080600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff169350600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600601549250600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600701549150600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050160009054906101000a900460ff1690509193509193565b600080600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690508073ffffffffffffffffffffffffffffffffffffffff166370a08231846040518263ffffffff1660e01b815260040161119f9190612b2f565b602060405180830381865afa1580156111bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111e09190613687565b915050919050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806112765750611247611eb2565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6112b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016112ac90613241565b60405180910390fd5b60006112bf610592565b905060005b6004805490508110156114fb57828015611365575060076000600483815481106112f1576112f0613009565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b156113b6576113b16004828154811061138157611380613009565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16611fb6565b6114e8565b60066000600483815481106113ce576113cd613009565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050160009054906101000a900460ff1615801561149857506009546114966004838154811061146657611465613009565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1661113e565b115b156114e7576114e6600482815481106114b4576114b3613009565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1685846126d1565b5b5b80806114f39061309b565b9150506112c4565b50505050565b6004818154811061151157600080fd5b906000526020600020016000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806115ce575061159f611eb2565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b61160d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161160490613241565b60405180910390fd5b600560008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561182e5783600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040181905550611b1d565b6001600560008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055506004859080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506040518061010001604052808673ffffffffffffffffffffffffffffffffffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff168152602001828152602001600015158152602001600081526020016000815250600660008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060408201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060608201518160030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506080820151816004015560a08201518160050160006101000a81548160ff02191690831515021790555060c0820151816006015560e082015181600701559050505b7f5446ab0ba7c017f50a3b977101d494eff5d7d9b6f5d9a22515377006c309438a8583868685604051611b549594939291906136b4565b60405180910390a15050505050565b600080600080600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169250600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169150600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169350600660008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206004015490509193509193565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480611d725750611d43611eb2565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b611db1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611da890613241565b60405180910390fd5b600560008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615611e975780600660008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050160006101000a81548160ff0219169083151502179055507f86a5c093bb99c6d06a96c424a351d83258cf9b1438445e973896d74c3edf64eb8282604051611e8e929190613707565b60405180910390a15b5050565b611ea36127d7565b611eae823383612919565b5050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60006060611f0d6127d7565b6000808773ffffffffffffffffffffffffffffffffffffffff16878787604051611f38929190613764565b60006040518083038185875af1925050503d8060008114611f75576040519150601f19603f3d011682016040523d82523d6000602084013e611f7a565b606091505b5091509150818193509350505094509492505050565b60095481565b60076020528060005260406000206000915054906101000a900460ff1681565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806120445750612015611eb2565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b612083576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161207a90613241565b60405180910390fd5b600760008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615612125576000600860008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050612123828261079e565b505b50565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806121b65750612187611eb2565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b6121f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121ec90613241565b60405180910390fd5b60005b60048054905081101561242e578180156122995750600760006004838154811061222557612224613009565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff165b156122ea576122e5600482815481106122b5576122b4613009565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16611fb6565b61241b565b600660006004838154811061230257612301613009565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050160009054906101000a900460ff161580156123cc57506009546123ca6004838154811061239a57612399613009565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1661113e565b115b1561241a57612419600482815481106123e8576123e7613009565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1684610e51565b5b5b80806124269061309b565b9150506121f8565b505050565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614806124c15750612492611eb2565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b612500576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124f790613241565b60405180910390fd5b600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16156126295781600760008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555080600860008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055507f70d7e641df56680393a21230bdc277feec8e8da8af9bdcc93f2bc14f83596ddb8383836040516126209392919061377d565b60405180910390a15b505050565b60056020528060005260406000206000915054906101000a900460ff1681565b6126566127d7565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036126c5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126bc90613826565b60405180910390fd5b6126ce81612855565b50565b600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16148061275f5750612730611eb2565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16145b61279e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161279590613241565b60405180910390fd5b60006127a98461113e565b905060008282856127ba91906135d0565b6127c49190613641565b90506127d0858261079e565b5050505050565b6127df612a4f565b73ffffffffffffffffffffffffffffffffffffffff166127fd611eb2565b73ffffffffffffffffffffffffffffffffffffffff1614612853576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161284a90613892565b60405180910390fd5b565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050816000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6000808473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb858560405160240161294b929190613261565b6040516020818303038152906040529060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516129999190613369565b6000604051808303816000865af19150503d80600081146129d6576040519150601f19603f3d011682016040523d82523d6000602084013e6129db565b606091505b5091509150818015612a095750600081511480612a08575080806020019051810190612a07919061329f565b5b5b612a48576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a3f906138fe565b60405180910390fd5b5050505050565b600033905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612a8c82612a61565b9050919050565b612a9c81612a81565b8114612aa757600080fd5b50565b600081359050612ab981612a93565b92915050565b600060208284031215612ad557612ad4612a57565b5b6000612ae384828501612aaa565b91505092915050565b6000819050919050565b612aff81612aec565b82525050565b6000602082019050612b1a6000830184612af6565b92915050565b612b2981612a81565b82525050565b6000602082019050612b446000830184612b20565b92915050565b612b5381612aec565b8114612b5e57600080fd5b50565b600081359050612b7081612b4a565b92915050565b60008060408385031215612b8d57612b8c612a57565b5b6000612b9b85828601612aaa565b9250506020612bac85828601612b61565b9150509250929050565b600060208284031215612bcc57612bcb612a57565b5b6000612bda84828501612b61565b91505092915050565b60008115159050919050565b612bf881612be3565b82525050565b6000608082019050612c136000830187612bef565b612c206020830186612af6565b612c2d6040830185612af6565b612c3a6060830184612bef565b95945050505050565b612c4c81612be3565b8114612c5757600080fd5b50565b600081359050612c6981612c43565b92915050565b60008060408385031215612c8657612c85612a57565b5b6000612c9485828601612b61565b9250506020612ca585828601612c5a565b9150509250929050565b600080600080600060a08688031215612ccb57612cca612a57565b5b6000612cd988828901612aaa565b9550506020612cea88828901612aaa565b9450506040612cfb88828901612aaa565b9350506060612d0c88828901612aaa565b9250506080612d1d88828901612b61565b9150509295509295909350565b6000608082019050612d3f6000830187612b20565b612d4c6020830186612b20565b612d596040830185612b20565b612d666060830184612af6565b95945050505050565b60008060408385031215612d8657612d85612a57565b5b6000612d9485828601612aaa565b9250506020612da585828601612c5a565b9150509250929050565b600080fd5b600080fd5b600080fd5b60008083601f840112612dd457612dd3612daf565b5b8235905067ffffffffffffffff811115612df157612df0612db4565b5b602083019150836001820283011115612e0d57612e0c612db9565b5b9250929050565b60008060008060608587031215612e2e57612e2d612a57565b5b6000612e3c87828801612aaa565b9450506020612e4d87828801612b61565b935050604085013567ffffffffffffffff811115612e6e57612e6d612a5c565b5b612e7a87828801612dbe565b925092505092959194509250565b600081519050919050565b600082825260208201905092915050565b60005b83811015612ec2578082015181840152602081019050612ea7565b60008484015250505050565b6000601f19601f8301169050919050565b6000612eea82612e88565b612ef48185612e93565b9350612f04818560208601612ea4565b612f0d81612ece565b840191505092915050565b6000604082019050612f2d6000830185612bef565b8181036020830152612f3f8184612edf565b90509392505050565b6000602082019050612f5d6000830184612bef565b92915050565b600080600060608486031215612f7c57612f7b612a57565b5b6000612f8a86828701612aaa565b9350506020612f9b86828701612c5a565b9250506040612fac86828701612b61565b9150509250925092565b600080600060608486031215612fcf57612fce612a57565b5b6000612fdd86828701612aaa565b9350506020612fee86828701612b61565b9250506040612fff86828701612b61565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061307282612aec565b915061307d83612aec565b925082820190508082111561309557613094613038565b5b92915050565b60006130a682612aec565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036130d8576130d7613038565b5b600182019050919050565b60006040820190506130f86000830185612b20565b6131056020830184612b20565b9392505050565b600082825260208201905092915050565b7f506f6f6c206973206e6f74206163746976650000000000000000000000000000600082015250565b600061315360128361310c565b915061315e8261311d565b602082019050919050565b6000602082019050818103600083015261318281613146565b9050919050565b7f506f6f6c20697320736d616c6c00000000000000000000000000000000000000600082015250565b60006131bf600d8361310c565b91506131ca82613189565b602082019050919050565b600060208201905081810360008301526131ee816131b2565b9050919050565b7f4e6f74206f776e6572206f72206f70657261746f720000000000000000000000600082015250565b600061322b60158361310c565b9150613236826131f5565b602082019050919050565b6000602082019050818103600083015261325a8161321e565b9050919050565b60006040820190506132766000830185612b20565b6132836020830184612af6565b9392505050565b60008151905061329981612c43565b92915050565b6000602082840312156132b5576132b4612a57565b5b60006132c38482850161328a565b91505092915050565b600060c0820190506132e16000830189612b20565b6132ee6020830188612b20565b6132fb6040830187612b20565b6133086060830186612b20565b6133156080830185612af6565b61332260a0830184612af6565b979650505050505050565b600081905092915050565b600061334382612e88565b61334d818561332d565b935061335d818560208601612ea4565b80840191505092915050565b60006133758284613338565b915081905092915050565b7f64656c656761746563616c6c206661696c656400000000000000000000000000600082015250565b60006133b660138361310c565b91506133c182613380565b602082019050919050565b600060208201905081810360008301526133e5816133a9565b9050919050565b600060ff82169050919050565b613402816133ec565b811461340d57600080fd5b50565b60008151905061341f816133f9565b92915050565b60006020828403121561343b5761343a612a57565b5b600061344984828501613410565b91505092915050565b60008160011c9050919050565b6000808291508390505b60018511156134a95780860481111561348557613484613038565b5b60018516156134945780820291505b80810290506134a285613452565b9450613469565b94509492505050565b6000826134c2576001905061357e565b816134d0576000905061357e565b81600181146134e657600281146134f05761351f565b600191505061357e565b60ff84111561350257613501613038565b5b8360020a91508482111561351957613518613038565b5b5061357e565b5060208310610133831016604e8410600b84101617156135545782820a90508381111561354f5761354e613038565b5b61357e565b613561848484600161345f565b9250905081840481111561357857613577613038565b5b81810290505b9392505050565b600061359082612aec565b915061359b836133ec565b92506135c87fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846134b2565b905092915050565b60006135db82612aec565b91506135e683612aec565b92508282026135f481612aec565b9150828204841483151761360b5761360a613038565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600061364c82612aec565b915061365783612aec565b92508261366757613666613612565b5b828204905092915050565b60008151905061368181612b4a565b92915050565b60006020828403121561369d5761369c612a57565b5b60006136ab84828501613672565b91505092915050565b600060a0820190506136c96000830188612b20565b6136d66020830187612b20565b6136e36040830186612b20565b6136f06060830185612b20565b6136fd6080830184612af6565b9695505050505050565b600060408201905061371c6000830185612b20565b6137296020830184612bef565b9392505050565b82818337600083830152505050565b600061374b838561332d565b9350613758838584613730565b82840190509392505050565b600061377182848661373f565b91508190509392505050565b60006060820190506137926000830186612b20565b61379f6020830185612bef565b6137ac6040830184612af6565b949350505050565b7f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160008201527f6464726573730000000000000000000000000000000000000000000000000000602082015250565b600061381060268361310c565b915061381b826137b4565b604082019050919050565b6000602082019050818103600083015261383f81613803565b9050919050565b7f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572600082015250565b600061387c60208361310c565b915061388782613846565b602082019050919050565b600060208201905081810360008301526138ab8161386f565b9050919050565b7f5472616e7366657248656c7065723a205452414e534645525f4641494c454400600082015250565b60006138e8601f8361310c565b91506138f3826138b2565b602082019050919050565b60006020820190508181036000830152613917816138db565b905091905056

Verified Source Code Partial Match

Compiler: v0.8.21+commit.d9974bed EVM: london Optimization: No
IFxs.sol 46 lines
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.19;

interface IFxs {
  function DEFAULT_ADMIN_ROLE() external view returns(bytes32);
  function FRAXStablecoinAdd() external view returns(address);
  function FXS_DAO_min() external view returns(uint256);
  function allowance(address owner, address spender) external view returns(uint256);
  function approve(address spender, uint256 amount) external returns(bool);
  function balanceOf(address account) external view returns(uint256);
  function burn(uint256 amount) external;
  function burnFrom(address account, uint256 amount) external;
  function checkpoints(address, uint32) external view returns(uint32 fromBlock, uint96 votes);
  function decimals() external view returns(uint8);
  function decreaseAllowance(address spender, uint256 subtractedValue) external returns(bool);
  function genesis_supply() external view returns(uint256);
  function getCurrentVotes(address account) external view returns(uint96);
  function getPriorVotes(address account, uint256 blockNumber) external view returns(uint96);
  function getRoleAdmin(bytes32 role) external view returns(bytes32);
  function getRoleMember(bytes32 role, uint256 index) external view returns(address);
  function getRoleMemberCount(bytes32 role) external view returns(uint256);
  function grantRole(bytes32 role, address account) external;
  function hasRole(bytes32 role, address account) external view returns(bool);
  function increaseAllowance(address spender, uint256 addedValue) external returns(bool);
  function mint(address to, uint256 amount) external;
  function name() external view returns(string memory);
  function numCheckpoints(address) external view returns(uint32);
  function oracle_address() external view returns(address);
  function owner_address() external view returns(address);
  function pool_burn_from(address b_address, uint256 b_amount) external;
  function pool_mint(address m_address, uint256 m_amount) external;
  function renounceRole(bytes32 role, address account) external;
  function revokeRole(bytes32 role, address account) external;
  function setFRAXAddress(address frax_contract_address) external;
  function setFXSMinDAO(uint256 min_FXS) external;
  function setOracle(address new_oracle) external;
  function setOwner(address _owner_address) external;
  function setTimelock(address new_timelock) external;
  function symbol() external view returns(string memory);
  function timelock_address() external view returns(address);
  function toggleVotes() external;
  function totalSupply() external view returns(uint256);
  function trackingVotes() external view returns(bool);
  function transfer(address recipient, uint256 amount) external returns(bool);
  function transferFrom(address sender, address recipient, uint256 amount) external returns(bool);
}
IFrax.sol 73 lines
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.19;

interface IFrax {
  function COLLATERAL_RATIO_PAUSER() external view returns (bytes32);
  function DEFAULT_ADMIN_ADDRESS() external view returns (address);
  function DEFAULT_ADMIN_ROLE() external view returns (bytes32);
  function addPool(address pool_address ) external;
  function allowance(address owner, address spender ) external view returns (uint256);
  function approve(address spender, uint256 amount ) external returns (bool);
  function balanceOf(address account ) external view returns (uint256);
  function burn(uint256 amount ) external;
  function burnFrom(address account, uint256 amount ) external;
  function collateral_ratio_paused() external view returns (bool);
  function controller_address() external view returns (address);
  function creator_address() external view returns (address);
  function decimals() external view returns (uint8);
  function decreaseAllowance(address spender, uint256 subtractedValue ) external returns (bool);
  function eth_usd_consumer_address() external view returns (address);
  function eth_usd_price() external view returns (uint256);
  function frax_eth_oracle_address() external view returns (address);
  function frax_info() external view returns (uint256, uint256, uint256, uint256, uint256, uint256, uint256, uint256);
  function frax_pools(address ) external view returns (bool);
  function frax_pools_array(uint256 ) external view returns (address);
  function frax_price() external view returns (uint256);
  function frax_step() external view returns (uint256);
  function fxs_address() external view returns (address);
  function fxs_eth_oracle_address() external view returns (address);
  function fxs_price() external view returns (uint256);
  function genesis_supply() external view returns (uint256);
  function getRoleAdmin(bytes32 role ) external view returns (bytes32);
  function getRoleMember(bytes32 role, uint256 index ) external view returns (address);
  function getRoleMemberCount(bytes32 role ) external view returns (uint256);
  function globalCollateralValue() external view returns (uint256);
  function global_collateral_ratio() external view returns (uint256);
  function grantRole(bytes32 role, address account ) external;
  function hasRole(bytes32 role, address account ) external view returns (bool);
  function increaseAllowance(address spender, uint256 addedValue ) external returns (bool);
  function last_call_time() external view returns (uint256);
  function minting_fee() external view returns (uint256);
  function name() external view returns (string memory);
  function owner_address() external view returns (address);
  function pool_burn_from(address b_address, uint256 b_amount ) external;
  function pool_mint(address m_address, uint256 m_amount ) external;
  function price_band() external view returns (uint256);
  function price_target() external view returns (uint256);
  function redemption_fee() external view returns (uint256);
  function refreshCollateralRatio() external;
  function refresh_cooldown() external view returns (uint256);
  function removePool(address pool_address ) external;
  function renounceRole(bytes32 role, address account ) external;
  function revokeRole(bytes32 role, address account ) external;
  function setController(address _controller_address ) external;
  function setETHUSDOracle(address _eth_usd_consumer_address ) external;
  function setFRAXEthOracle(address _frax_oracle_addr, address _weth_address ) external;
  function setFXSAddress(address _fxs_address ) external;
  function setFXSEthOracle(address _fxs_oracle_addr, address _weth_address ) external;
  function setFraxStep(uint256 _new_step ) external;
  function setMintingFee(uint256 min_fee ) external;
  function setOwner(address _owner_address ) external;
  function setPriceBand(uint256 _price_band ) external;
  function setPriceTarget(uint256 _new_price_target ) external;
  function setRedemptionFee(uint256 red_fee ) external;
  function setRefreshCooldown(uint256 _new_cooldown ) external;
  function setTimelock(address new_timelock ) external;
  function symbol() external view returns (string memory);
  function timelock_address() external view returns (address);
  function toggleCollateralRatio() external;
  function totalSupply() external view returns (uint256);
  function transfer(address recipient, uint256 amount ) external returns (bool);
  function transferFrom(address sender, address recipient, uint256 amount ) external returns (bool);
  function weth_address() external view returns (address);
}
TransferHelper.sol 28 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.11;

// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false
library TransferHelper {
    function safeApprove(address token, address to, uint value) internal {
        // bytes4(keccak256(bytes('approve(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED');
    }

    function safeTransfer(address token, address to, uint value) internal {
        // bytes4(keccak256(bytes('transfer(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED');
    }

    function safeTransferFrom(address token, address from, address to, uint value) internal {
        // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');
    }

    function safeTransferETH(address to, uint value) internal {
        (bool success,) = to.call{value:value}(new bytes(0));
        require(success, 'TransferHelper: ETH_TRANSFER_FAILED');
    }
}
IncentivizingLiquidityAMO.sol 400 lines
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.19;

// ====================================================================
// |     ______                   _______                             |
// |    / _____________ __  __   / ____(_____  ____ _____  ________   |
// |   / /_  / ___/ __ `| |/_/  / /_  / / __ \/ __ `/ __ \/ ___/ _ \  |
// |  / __/ / /  / /_/ _>  <   / __/ / / / / / /_/ / / / / /__/  __/  |
// | /_/   /_/   \__,_/_/|_|  /_/   /_/_/ /_/\__,_/_/ /_/\___/\___/   |
// |                                                                  |
// ====================================================================
// ================== IncentivizingLiquidityAMO =======================
// ====================================================================
// Frax Finance: https://github.com/FraxFinance

// Primary Author(s)
// Amirnader Aghayeghazvini: https://github.com/amirnader-ghazvini

// Reviewer(s) / Contributor(s)
// Dennis: https://github.com/denett

import "./interfaces/IFrax.sol";
import "./interfaces/IFxs.sol";
import "./interfaces/IIncentivizationHandler.sol";
import "./Uniswap/TransferHelper.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract IncentivizingLiquidityAmo is Ownable {
    /* ============================================= STATE VARIABLES ==================================================== */

    // Addresses Config
    address public operatorAddress;
    address public targetTokenAddress; // Token that AMO incentivize
    address public incentiveTokenAddress; // Token that AMO uses as an incentive
    

    // Pools related
    address[] public poolArray;
    struct LiquidityPool {
        // Pool Addresses
        address poolAddress; // Where the actual tokens are in the pool
        address incentivePoolAddress; // Contract that handle incentive distribution e.g. Bribe contract
        address incentivizationHandlerAddress; // Incentive handler contract e.g. votemarket handler
        address gaugeAddress; // Gauge address
        uint256 incentivizationId; // Votemarket Bounty ID
        bool isPaused;
        uint lastIncentivizationTimestamp; // timestamp of last time this pool was incentivized
        uint lastIncentivizationAmount; // Max amount of incentives
    }
    mapping(address => bool) public poolInitialized;
    mapping(address => LiquidityPool) private poolInfo;

    // Constant Incentivization can be set (e.g. DAO Deal)
    mapping(address => bool) public poolHasFixedIncent; 
    mapping(address => uint256) public poolFixedIncentAmount; // Constant Incentivization amount

    // Configurations
    uint256 public minTvl; // Min TVL of pool for being considered for incentivization

    /* =============================================== CONSTRUCTOR ====================================================== */

    /// @notice constructor
    /// @param _operatorAddress Address of AMO Operator
    /// @param _targetTokenAddress Address of Token that AMO incentivize (e.g. crvFRAX)
    /// @param _incentiveTokenAddress Address of Token that AMO uses as an incentive (e.g. FXS)
    /// @param _minTvl Min TVL of pool for being considered for incentivization
    constructor(
        address _operatorAddress,
        address _targetTokenAddress,
        address _incentiveTokenAddress,
        uint256 _minTvl
    ) Ownable() {
        operatorAddress = _operatorAddress;
        targetTokenAddress = _targetTokenAddress;
        incentiveTokenAddress = _incentiveTokenAddress;
        minTvl = _minTvl;
        emit StartAMO(_operatorAddress, _targetTokenAddress, _incentiveTokenAddress);
    }

    /* ================================================ MODIFIERS ======================================================= */

    modifier onlyByOwnerOperator() {
        require(msg.sender == operatorAddress || msg.sender == owner(), "Not owner or operator");
        _;
    }

    modifier activePool(address _poolAddress) {
        require(poolInitialized[_poolAddress] && !poolInfo[_poolAddress].isPaused, "Pool is not active");
        require(showPoolTvl(_poolAddress) > minTvl, "Pool is small");
        _;
    }

    /* ================================================= EVENTS ========================================================= */

    /// @notice The ```StartAMO``` event fires when the AMO deploys
    /// @param _operatorAddress Address of operator
    /// @param _targetTokenAddress Address of Token that AMO incentivize (e.g. crvFRAX)
    /// @param _incentiveTokenAddress Address of Token that AMO uses as an incentive (e.g. FXS)
    event StartAMO(address _operatorAddress, address _targetTokenAddress, address _incentiveTokenAddress);

    /// @notice The ```SetOperator``` event fires when the operatorAddress is set
    /// @param _oldAddress The original address
    /// @param _newAddress The new address
    event SetOperator(address _oldAddress, address _newAddress);

    /// @notice The ```AddOrSetPool``` event fires when a pool is added or modified
    /// @param _poolAddress The pool address
    /// @param _gaugeAddress The gauge address
    /// @param _incentivePoolAddress Contract that handle incentive distribution e.g. Bribe contract
    /// @param _incentivizationHandlerAddress Incentive handler contract e.g. votemarket handler
    /// @param _indexId indexID in Votium or Votemarket
    event AddOrSetPool(
        address _poolAddress,
        address _gaugeAddress,
        address _incentivePoolAddress,
        address _incentivizationHandlerAddress,
        uint256 _indexId
    );

    /// @notice The ```ChangePauseStatusPool``` event fires when a pool is added or modified
    /// @param _poolAddress The pool address
    /// @param _isPaused Pool Pause Status
    event ChangePauseStatusPool(address _poolAddress, bool _isPaused);

    /// @notice The ```SetPoolFixedIncent``` event fires when a pool's constant incentivization is updated 
    /// @param _poolAddress The pool address
    /// @param _hasFixedIncent Pool Deal Status
    /// @param _amountPerCycle Pool Deal Amount
    event SetPoolFixedIncent(address _poolAddress, bool _hasFixedIncent, uint256 _amountPerCycle);

    /// @notice The ```IncentivizePool``` event fires when a deposit happens to a pair
    /// @param _poolAddress The pool address
    /// @param _amount Incentive amount
    event IncentivizePool(address _poolAddress, uint256 _amount);

    /* ================================================== VIEWS ========================================================= */

    /// @notice Show TVL of targeted token in all active pools
    /// @return TVL of targeted token in all active pools
    function showActivePoolsTvl() public view returns (uint256) {
        uint tvl = 0;
        for (uint i = 0; i < poolArray.length; i++) {
            if (!poolInfo[poolArray[i]].isPaused) {
                tvl += showPoolTvl(poolArray[i]);
            }
        }
        return tvl;
    }

    /// @notice Show TVL of targeted token in liquidity pool
    /// @param _poolAddress Address of liquidity pool
    /// @return TVL of targeted token in liquidity pool
    function showPoolTvl(address _poolAddress) public view returns (uint256) {
        ERC20 targetToken = ERC20(targetTokenAddress);
        return targetToken.balanceOf(_poolAddress);
    }

    /// @notice Show Pool parameters
    /// @param _poolAddress Address of liquidity pool
    /// @return _gaugeAddress Gauge Contract Address
    /// @return _incentivePoolAddress Contract that handle incentive distribution e.g. Bribe contract
    /// @return _incentivizationHandlerAddress Incentive handler contract e.g. votemarket handler
    /// @return _incentivizationId Pool General Incentivization ID (e.g. in Votemarket it is BountyID)
    function showPoolInfo(
        address _poolAddress
    )
        external
        view
        returns (
            address _gaugeAddress,
            address _incentivePoolAddress,
            address _incentivizationHandlerAddress,
            uint256 _incentivizationId
        )
    {
        _incentivePoolAddress = poolInfo[_poolAddress].incentivePoolAddress;
        _incentivizationHandlerAddress = poolInfo[_poolAddress].incentivizationHandlerAddress;
        _gaugeAddress = poolInfo[_poolAddress].gaugeAddress;
        _incentivizationId = poolInfo[_poolAddress].incentivizationId;
    }

    /// @notice Show Pool status
    /// @param _poolAddress Address of liquidity pool
    /// @return _isInitialized Pool registered or not
    /// @return _lastIncentivizationTimestamp timestamp of last time this pool was incentivized
    /// @return _lastIncentivizationAmount last cycle incentive amount
    /// @return _isPaused puased or not
    function showPoolStatus(
        address _poolAddress
    )
        external
        view
        returns (
            bool _isInitialized,
            uint _lastIncentivizationTimestamp,
            uint _lastIncentivizationAmount,
            bool _isPaused
        )
    {
        _isInitialized = poolInitialized[_poolAddress];
        _lastIncentivizationTimestamp = poolInfo[_poolAddress].lastIncentivizationTimestamp;
        _lastIncentivizationAmount = poolInfo[_poolAddress].lastIncentivizationAmount;
        _isPaused = poolInfo[_poolAddress].isPaused;
    }

    /* ============================================== INCENTIVIZATION FUNCTIONS ==================================================== */

    /// @notice Function to deposit incentives to one pool
    /// @param _poolAddress Address of liquidity pool
    /// @param _amount Amount of incentives to be deposited
    function incentivizePoolByAmount(
        address _poolAddress,
        uint256 _amount
    ) public activePool(_poolAddress) onlyByOwnerOperator {
        ERC20 _incentiveToken = ERC20(incentiveTokenAddress);
        _incentiveToken.approve(poolInfo[_poolAddress].incentivePoolAddress, _amount);

        (bool success, ) = poolInfo[_poolAddress].incentivizationHandlerAddress.delegatecall(
            abi.encodeWithSignature(
                "incentivizePool(address,address,address,address,uint256,uint256)",
                _poolAddress,
                poolInfo[_poolAddress].gaugeAddress,
                poolInfo[_poolAddress].incentivePoolAddress,
                incentiveTokenAddress,
                poolInfo[_poolAddress].incentivizationId,
                _amount
            )
        );
        require(success, "delegatecall failed");

        poolInfo[_poolAddress].lastIncentivizationTimestamp = block.timestamp;
        poolInfo[_poolAddress].lastIncentivizationAmount = _amount;
        emit IncentivizePool(_poolAddress, _amount);
    }

    /// @notice Function to deposit incentives to one pool (based on ratio)
    /// @param _poolAddress Address of liquidity pool
    /// @param _totalIncentAmount Total budget for incentivization
    /// @param _totalTvl Total active pools TVL
    function incentivizePoolByTvl(
        address _poolAddress,
        uint256 _totalIncentAmount,
        uint256 _totalTvl
    ) public onlyByOwnerOperator {
        uint256 _poolTvl = showPoolTvl(_poolAddress);
        uint256 _amount = (_totalIncentAmount * _poolTvl) / _totalTvl;
        incentivizePoolByAmount(_poolAddress, _amount);
    }

    /// @notice Function to deposit incentives to one pool (based on budget per unit)
    /// @param _poolAddress Address of liquidity pool
    /// @param _unitIncentAmount Incentive per single unit of target Token
    function incentivizePoolByUnitBudget(
        address _poolAddress,
        uint256 _unitIncentAmount
    ) public onlyByOwnerOperator {
        uint256 _poolTvl = showPoolTvl(_poolAddress);
        uint256 _amount = (_unitIncentAmount * _poolTvl) / (10 ** ERC20(targetTokenAddress).decimals());
        incentivizePoolByAmount(_poolAddress, _amount);
    }

    /// @notice Function to deposit incentives to one pool (based on Constant Incentivization)
    /// @param _poolAddress Address of liquidity pool
    function incentivizePoolByFixedIncent(
        address _poolAddress
    ) public onlyByOwnerOperator {
        if (poolHasFixedIncent[_poolAddress]){
            uint256 _amount = poolFixedIncentAmount[_poolAddress];
            incentivizePoolByAmount(_poolAddress, _amount);
        }
    }

    /// Functions For depositing incentives to all active pools

    /// @notice Function to deposit incentives to all active pools (based on TVL ratio)
    /// @param _totalIncentAmount Total Incentive budget
    /// @param _FixedIncent Incentivize considering FixedIncent
    function incentivizeAllPoolsByTvl(uint256 _totalIncentAmount, bool _FixedIncent) public onlyByOwnerOperator {
        uint256 _totalTvl = showActivePoolsTvl();
        for (uint i = 0; i < poolArray.length; i++) {
            if (_FixedIncent && poolHasFixedIncent[poolArray[i]]) {
                incentivizePoolByFixedIncent(poolArray[i]);
            } else if (!poolInfo[poolArray[i]].isPaused && showPoolTvl(poolArray[i]) > minTvl) {
                incentivizePoolByTvl(poolArray[i], _totalIncentAmount, _totalTvl);
            }
        }
    }
    
    /// @notice Function to deposit incentives to all active pools (based on budget per unit of target Token)
    /// @param _unitIncentAmount Incentive per single unit of target Token
    /// @param _FixedIncent Incentivize considering FixedIncent
    function incentivizeAllPoolsByUnitBudget(uint256 _unitIncentAmount, bool _FixedIncent) public onlyByOwnerOperator {
        for (uint i = 0; i < poolArray.length; i++) {
            if (_FixedIncent && poolHasFixedIncent[poolArray[i]]) {
                incentivizePoolByFixedIncent(poolArray[i]);
            } else if (!poolInfo[poolArray[i]].isPaused && showPoolTvl(poolArray[i]) > minTvl) {
                incentivizePoolByUnitBudget(poolArray[i], _unitIncentAmount);
            }
        }
    }

    /// @notice Add/Set liquidity pool
    /// @param _poolAddress Address of liquidity pool
    /// @param _incentivePoolAddress Contract that handle incentive distribution e.g. Bribe contract
    /// @param _incentivizationHandlerAddress Incentive handler contract e.g. votemarket handler
    /// @param _gaugeAddress Address of liquidity pool gauge
    /// @param _incentivizationId Pool General Incentivization ID (e.g. in Votemarket it is BountyID)
    function addOrSetPool(
        address _poolAddress,
        address _incentivePoolAddress,
        address _incentivizationHandlerAddress,
        address _gaugeAddress,
        uint256 _incentivizationId
    ) external onlyByOwnerOperator {
        if (poolInitialized[_poolAddress]) {
            poolInfo[_poolAddress].incentivePoolAddress = _incentivePoolAddress;
            poolInfo[_poolAddress].incentivizationHandlerAddress = _incentivizationHandlerAddress;
            poolInfo[_poolAddress].gaugeAddress = _gaugeAddress;
            poolInfo[_poolAddress].incentivizationId = _incentivizationId;
        } else {
            poolInitialized[_poolAddress] = true;
            poolArray.push(_poolAddress);
            poolInfo[_poolAddress] = LiquidityPool({
                poolAddress: _poolAddress,
                incentivePoolAddress: _incentivePoolAddress,
                incentivizationHandlerAddress: _incentivizationHandlerAddress,
                gaugeAddress: _gaugeAddress,
                lastIncentivizationTimestamp: 0,
                lastIncentivizationAmount: 0,
                isPaused: false,
                incentivizationId: _incentivizationId
            });
        }

        emit AddOrSetPool(
            _poolAddress,
            _gaugeAddress,
            _incentivePoolAddress,
            _incentivizationHandlerAddress,
            _incentivizationId
        );
    }

    /// @notice Pause/Unpause liquidity pool
    /// @param _poolAddress Address of liquidity pool
    /// @param _isPaused bool
    function pausePool(address _poolAddress, bool _isPaused) external onlyByOwnerOperator {
        if (poolInitialized[_poolAddress]) {
            poolInfo[_poolAddress].isPaused = _isPaused;
            emit ChangePauseStatusPool(_poolAddress, _isPaused);
        }
    }

    /// @notice Add/Change/Remove Constant Incentivization can be set (e.g. DAO Deal)
    /// @param _poolAddress Address of liquidity pool
    /// @param _hasFixedIncent bool
    /// @param _amountPerCycle Amount of constant incentives
    function setFixedIncent(address _poolAddress, bool _hasFixedIncent, uint256 _amountPerCycle) external onlyByOwnerOperator {
        if (poolInitialized[_poolAddress]) {
            poolHasFixedIncent[_poolAddress] = _hasFixedIncent;
            poolFixedIncentAmount[_poolAddress] = _amountPerCycle;
            emit SetPoolFixedIncent(_poolAddress, _hasFixedIncent, _amountPerCycle);
        }
    }

    /* ====================================== RESTRICTED GOVERNANCE FUNCTIONS =========================================== */

    /// @notice Change the Operator address
    /// @param _newOperatorAddress Operator address
    function setOperatorAddress(address _newOperatorAddress) external onlyOwner {
        emit SetOperator(operatorAddress, _newOperatorAddress);
        operatorAddress = _newOperatorAddress;
    }

    /// @notice Change the Min TVL for incentivization
    /// @param _minTvl Min TVL of pool for being considered for incentivization
    function setMinTvl(uint256 _minTvl) external onlyOwner {
        minTvl = _minTvl;
    }

    /// @notice Recover ERC20 tokens
    /// @param tokenAddress address of ERC20 token
    /// @param tokenAmount amount to be withdrawn
    function recoverERC20(address tokenAddress, uint256 tokenAmount) external onlyOwner {
        // Can only be triggered by owner
        TransferHelper.safeTransfer(address(tokenAddress), msg.sender, tokenAmount);
    }

    // Generic proxy
    function execute(
        address _to,
        uint256 _value,
        bytes calldata _data
    ) external onlyOwner returns (bool, bytes memory) {
        (bool success, bytes memory result) = _to.call{ value: _value }(_data);
        return (success, result);
    }
}
IIncentivizationHandler.sol 12 lines
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.19;

interface IIncentivizationHandler {
  function incentivizePool(
    address poolAddress, 
    address gaugeAddress,
    address incentivePoolAdderss, 
    address incentiveTokenAddress,
    uint256 indexId, 
    uint256 amount) external;
}
Address.sol 244 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     *
     * Furthermore, `isContract` will also return true if the target contract within
     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
     * which only has an effect at the end of a transaction.
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}
Context.sol 24 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

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

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}
Ownable.sol 83 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}
ERC20.sol 365 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.0;

import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";

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

    mapping(address => mapping(address => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

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

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

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

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

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

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

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

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

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

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

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, allowance(owner, spender) + addedValue);
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        address owner = _msgSender();
        uint256 currentAllowance = allowance(owner, spender);
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(owner, spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    /**
     * @dev Moves `amount` of tokens from `from` to `to`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     */
    function _transfer(address from, address to, uint256 amount) internal virtual {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(from, to, amount);

        uint256 fromBalance = _balances[from];
        require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[from] = fromBalance - amount;
            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
            // decrementing then incrementing.
            _balances[to] += amount;
        }

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        unchecked {
            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
            _balances[account] += amount;
        }
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
            // Overflow not possible: amount <= accountBalance <= totalSupply.
            _totalSupply -= amount;
        }

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(address owner, address spender, uint256 amount) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.
     *
     * Does not update the allowance amount in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Might emit an {Approval} event.
     */
    function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            require(currentAllowance >= amount, "ERC20: insufficient allowance");
            unchecked {
                _approve(owner, spender, currentAllowance - amount);
            }
        }
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * has been transferred to `to`.
     * - when `from` is zero, `amount` tokens have been minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}
}
IERC20.sol 78 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

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

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

    /**
     * @dev Returns the 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 `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, 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 `from` to `to` 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 from, address to, uint256 amount) external returns (bool);
}
SafeERC20.sol 143 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Compatible with tokens that require the approval to be set to
     * 0 before setting it to a non-zero value.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
     * Revert on invalid signature.
     */
    function safePermit(
        IERC20Permit token,
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        uint256 nonceBefore = token.nonces(owner);
        token.permit(owner, spender, value, deadline, v, r, s);
        uint256 nonceAfter = token.nonces(owner);
        require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
        // and not revert is the subcall reverts.

        (bool success, bytes memory returndata) = address(token).call(data);
        return
            success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
    }
}
IERC20Permit.sol 60 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}
IERC20Metadata.sol 28 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";

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

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

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

Read Contract

incentiveTokenAddress 0x20263e87 → address
minTvl 0xb7540219 → uint256
operatorAddress 0x127effb2 → address
owner 0x8da5cb5b → address
poolArray 0x82eac7f0 → address
poolFixedIncentAmount 0x03ea9f1f → uint256
poolHasFixedIncent 0xd27761ef → bool
poolInitialized 0xee5b11c3 → bool
showActivePoolsTvl 0x0f37b6ba → uint256
showPoolInfo 0x86bfdb19 → address, address, address, uint256
showPoolStatus 0x7c43215f → bool, uint256, uint256, bool
showPoolTvl 0x81d81d2a → uint256
targetTokenAddress 0xae49945d → address

Write Contract 15 functions

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

addOrSetPool 0x843d96f2
address _poolAddress
address _incentivePoolAddress
address _incentivizationHandlerAddress
address _gaugeAddress
uint256 _incentivizationId
execute 0xb61d27f6
address _to
uint256 _value
bytes _data
returns: bool, bytes
incentivizeAllPoolsByTvl 0x81d8b3f8
uint256 _totalIncentAmount
bool _FixedIncent
incentivizeAllPoolsByUnitBudget 0xec06a89a
uint256 _unitIncentAmount
bool _FixedIncent
incentivizePoolByAmount 0x45c12626
address _poolAddress
uint256 _amount
incentivizePoolByFixedIncent 0xe390ddde
address _poolAddress
incentivizePoolByTvl 0xf7f2e80d
address _poolAddress
uint256 _totalIncentAmount
uint256 _totalTvl
incentivizePoolByUnitBudget 0x70c8f7fe
address _poolAddress
uint256 _unitIncentAmount
pausePool 0x88660611
address _poolAddress
bool _isPaused
recoverERC20 0x8980f11f
address tokenAddress
uint256 tokenAmount
renounceOwnership 0x715018a6
No parameters
setFixedIncent 0xec16bf47
address _poolAddress
bool _hasFixedIncent
uint256 _amountPerCycle
setMinTvl 0x60976e6f
uint256 _minTvl
setOperatorAddress 0x2f1d5a60
address _newOperatorAddress
transferOwnership 0xf2fde38b
address newOwner

Recent Transactions

No transactions found for this address