Cryo Explorer Ethereum Mainnet

Address Contract Verified

Address 0xE95FEbF9b8623b1b3B79BF995491197A8b67D2A7
Balance 0 ETH
Nonce 1
Code Size 22337 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

22337 bytes
0x608060405234801561001057600080fd5b50600436106103155760003560e01c80639a6fc8f5116101a7578063d09dc339116100ee578063e76d516811610097578063f2fde38b11610071578063f2fde38b1461084f578063fbffd2c114610862578063feaf968c1461087557600080fd5b8063e76d516814610818578063eb45716314610829578063eb5dcd6c1461083c57600080fd5b8063e3d0e712116100c8578063e3d0e71214610793578063e4902f82146107a6578063e5fe4577146107ce57600080fd5b8063d09dc3391461076d578063daffc4b514610775578063dc7f01241461078657600080fd5b8063b121e14711610150578063b633620c1161012a578063b633620c14610736578063c107532914610749578063c4c92b371461075c57600080fd5b8063b121e147146106fd578063b1dc65a414610710578063b5ab58dc1461072357600080fd5b80639e3ceeab116101815780639e3ceeab146106a6578063a118f249146106b9578063afcb95d7146106cc57600080fd5b80639a6fc8f5146105f75780639bd2c0b1146106415780639c849b301461069357600080fd5b8063668a0f021161026b57806381ff7048116102145780638ac28d5a116101ee5780638ac28d5a1461059c5780638da5cb5b146105af57806398e5b12a146105d457600080fd5b806381ff7048146105515780638205bf6a146105815780638823da6c1461058957600080fd5b80637284e416116102455780637284e4161461053957806379ba5097146105415780638038e4a11461054957600080fd5b8063668a0f02146104e75780636b14daf8146104ef57806370da2f671461051257600080fd5b8063313ce567116102cd57806354fd4d50116102a757806354fd4d50146104b7578063643dc105146104bf578063666cab8d146104d257600080fd5b8063313ce567146104635780634fb174701461049c57806350d25bcd146104af57600080fd5b8063181f5a77116102fe578063181f5a771461034a57806322adbc781461035f578063299372681461039957600080fd5b80630a7569831461031a5780630eafb25b14610324575b600080fd5b61032261087d565b005b610337610332366004614b17565b6108e4565b6040519081526020015b60405180910390f35b610352610a05565b6040516103419190614b7a565b6103867f000000000000000000000000000000000000000000000000000000000000000181565b60405160179190910b8152602001610341565b610427600b546a0100000000000000000000810463ffffffff908116926e010000000000000000000000000000830482169272010000000000000000000000000000000000008104831692760100000000000000000000000000000000000000000000820416917a01000000000000000000000000000000000000000000000000000090910462ffffff1690565b6040805163ffffffff9687168152948616602086015292851692840192909252909216606082015262ffffff909116608082015260a001610341565b61048a7f000000000000000000000000000000000000000000000000000000000000001281565b60405160ff9091168152602001610341565b6103226104aa366004614b8d565b610a25565b610337610ca5565b610337600681565b6103226104cd366004614bd8565b610d63565b6104da61101e565b6040516103419190614c95565b610337611080565b6105026104fd366004614d78565b611127565b6040519015158152602001610341565b6103867f00000000000000000000ffffffffffffffffffffffffffffffffffffffffffff81565b61035261114f565b6103226111e6565b6103226112af565b600d54600a546040805163ffffffff80851682526401000000009094049093166020840152820152606001610341565b610337611317565b610322610597366004614b17565b6113ef565b6103226105aa366004614b17565b61148f565b6000546001600160a01b03165b6040516001600160a01b039091168152602001610341565b6105dc611501565b60405169ffffffffffffffffffff9091168152602001610341565b61060a610605366004614dc8565b611678565b6040805169ffffffffffffffffffff968716815260208101959095528401929092526060830152909116608082015260a001610341565b604080518082018252600e546001600160a01b0381168083527401000000000000000000000000000000000000000090910463ffffffff16602092830181905283519182529181019190915201610341565b6103226106a1366004614e40565b61172a565b6103226106b4366004614b17565b611920565b6103226106c7366004614b17565b6119b7565b600a54600b546040805160008152602081019390935261010090910460081c63ffffffff1690820152606001610341565b61032261070b366004614b17565b611a51565b61032261071e366004614eac565b611b45565b610337610731366004614f91565b612090565b610337610744366004614f91565b612130565b610322610757366004614faa565b6121c8565b6012546001600160a01b03166105bc565b61033761249c565b600f546001600160a01b03166105bc565b6015546105029060ff1681565b6103226107a1366004615097565b612545565b6107b96107b4366004614b17565b612dc1565b60405163ffffffff9091168152602001610341565b6107d6612e7f565b6040805195865263ffffffff909416602086015260ff9092169284019290925260179190910b606083015267ffffffffffffffff16608082015260a001610341565b6011546001600160a01b03166105bc565b610322610837366004615164565b612f44565b61032261084a366004614b8d565b613061565b61032261085d366004614b17565b6131b1565b610322610870366004614b17565b6131c2565b61060a6131d3565b610885613308565b60155460ff16156108e257601580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556040517f3be8a977a014527b50ae38adda80b56911c267328965c98ddc385d248f53963890600090a15b565b6001600160a01b03811660009081526002602090815260408083208151606081018352905460ff80821615158084526101008304909116948301949094526201000090046bffffffffffffffffffffffff16918101919091529061094b5750600092915050565b600b5460208201516000917201000000000000000000000000000000000000900463ffffffff169060069060ff16601f811061098957610989615192565b600881049190910154600b546109bf926007166004026101000a90910463ffffffff9081169166010000000000009004166151f0565b63ffffffff166109cf9190615214565b6109dd90633b9aca00615214565b905081604001516bffffffffffffffffffffffff16816109fd919061522b565b949350505050565b60606040518060600160405280602481526020016156e860249139905090565b610a2d613308565b6011546001600160a01b03908116908316819003610a4a57505050565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038416906370a0823190602401602060405180830381865afa158015610aa7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610acb919061523e565b50610ad4613362565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610b34573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b58919061523e565b6040517fa9059cbb0000000000000000000000000000000000000000000000000000000081526001600160a01b038581166004830152602482018390529192509083169063a9059cbb906044016020604051808303816000875af1158015610bc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610be89190615257565b610c395760405162461bcd60e51b815260206004820152601f60248201527f7472616e736665722072656d61696e696e672066756e6473206661696c65640060448201526064015b60405180910390fd5b601180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0386811691821790925560405190918416907f4966a50c93f855342ccf6c5c0d358b85b91335b2acedc7da0932f691f351711a90600090a350505b5050565b6000610ce8336000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061112792505050565b610d345760405162461bcd60e51b815260206004820152600960248201527f4e6f2061636365737300000000000000000000000000000000000000000000006044820152606401610c30565b600b546601000000000000900463ffffffff166000908152600c602052604090205460170b905090565b905090565b6012546001600160a01b0316610d816000546001600160a01b031690565b6001600160a01b0316336001600160a01b03161480610e2657506040517f6b14daf80000000000000000000000000000000000000000000000000000000081526001600160a01b03821690636b14daf890610de59033906000903690600401615279565b602060405180830381865afa158015610e02573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e269190615257565b610e725760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79206f776e65722662696c6c696e6741646d696e2063616e2063616c6c6044820152606401610c30565b610e7a613362565b600b80547fffffffffffffffffffffffffffff0000000000000000ffffffffffffffffffff166a010000000000000000000063ffffffff8981169182027fffffffffffffffffffffffffffff00000000ffffffffffffffffffffffffffff16929092176e010000000000000000000000000000898416908102919091177fffffffffffff0000000000000000ffffffffffffffffffffffffffffffffffff1672010000000000000000000000000000000000008985169081027fffffffffffff00000000ffffffffffffffffffffffffffffffffffffffffffff1691909117760100000000000000000000000000000000000000000000948916948502177fffffff000000ffffffffffffffffffffffffffffffffffffffffffffffffffff167a01000000000000000000000000000000000000000000000000000062ffffff89169081029190911790955560408051938452602084019290925290820152606081019190915260808101919091527f0bf184bf1bba9699114bdceddaf338a1b364252c5e497cc01918dde92031713f9060a00160405180910390a1505050505050565b6060600580548060200260200160405190810160405280929190818152602001828054801561107657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611058575b5050505050905090565b60006110c3336000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061112792505050565b61110f5760405162461bcd60e51b815260206004820152600960248201527f4e6f2061636365737300000000000000000000000000000000000000000000006044820152606401610c30565b600b546601000000000000900463ffffffff16905090565b60006111338383613746565b8061114657506001600160a01b03831632145b90505b92915050565b6060611192336000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061112792505050565b6111de5760405162461bcd60e51b815260206004820152600960248201527f4e6f2061636365737300000000000000000000000000000000000000000000006044820152606401610c30565b610d5e613776565b6001546001600160a01b031633146112405760405162461bcd60e51b815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610c30565b60008054337fffffffffffffffffffffffff0000000000000000000000000000000000000000808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6112b7613308565b60155460ff166108e257601580547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556040517faebf329500988c6488a0074e5a0a9ff304561fc5c6fc877aeb1d59c8282c348090600090a1565b600061135a336000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061112792505050565b6113a65760405162461bcd60e51b815260206004820152600960248201527f4e6f2061636365737300000000000000000000000000000000000000000000006044820152606401610c30565b50600b5463ffffffff660100000000000090910481166000908152600c60205260409020547c010000000000000000000000000000000000000000000000000000000090041690565b6113f7613308565b6001600160a01b03811660009081526016602052604090205460ff161561148c576001600160a01b03811660008181526016602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905590519182527f3d68a6fce901d20453d1a7aa06bf3950302a735948037deb182a8db66df2a0d191015b60405180910390a15b50565b6001600160a01b038181166000908152601360205260409020541633146114f85760405162461bcd60e51b815260206004820152601760248201527f4f6e6c792070617965652063616e2077697468647261770000000000000000006044820152606401610c30565b61148c816137ff565b600080546001600160a01b03163314806115a55750600f546040517f6b14daf80000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690636b14daf8906115649033906000903690600401615279565b602060405180830381865afa158015611581573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a59190615257565b6115f15760405162461bcd60e51b815260206004820152601d60248201527f4f6e6c79206f776e6572267265717565737465722063616e2063616c6c0000006044820152606401610c30565b600b54600a546040805191825263ffffffff6101008404600881901c8216602085015260ff811684840152915164ffffffffff9092169366010000000000009004169133917f41e3990591fd372502daa15842da15bc7f41c75309ab3ff4f56f1848c178825c9181900360600190a261166b8160016152b8565b63ffffffff169250505090565b60008060008060006116c1336000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061112792505050565b61170d5760405162461bcd60e51b815260206004820152600960248201527f4e6f2061636365737300000000000000000000000000000000000000000000006044820152606401610c30565b61171686613a4b565b945094509450945094505b91939590929450565b611732613308565b8281146117815760405162461bcd60e51b815260206004820181905260248201527f7472616e736d6974746572732e73697a6520213d207061796565732e73697a656044820152606401610c30565b60005b838110156119195760008585838181106117a0576117a0615192565b90506020020160208101906117b59190614b17565b905060008484848181106117cb576117cb615192565b90506020020160208101906117e09190614b17565b6001600160a01b03808416600090815260136020526040902054919250168015808061181d5750826001600160a01b0316826001600160a01b0316145b6118695760405162461bcd60e51b815260206004820152601160248201527f706179656520616c7265616479207365740000000000000000000000000000006044820152606401610c30565b6001600160a01b03848116600090815260136020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000168583169081179091559083161461190257826001600160a01b0316826001600160a01b0316856001600160a01b03167f78af32efdcad432315431e9b03d27e6cd98fb79c405fdc5af7c1714d9c0f75b360405160405180910390a45b505050508080611911906152d5565b915050611784565b5050505050565b611928613308565b600f546001600160a01b039081169082168114610ca157600f80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0384811691821790925560408051928416835260208301919091527f27b89aede8b560578baaa25ee5ce3852c5eecad1e114b941bbd89e1eb4bae63491015b60405180910390a15050565b6119bf613308565b6001600160a01b03811660009081526016602052604090205460ff1661148c576001600160a01b03811660008181526016602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905590519182527f87286ad1f399c8e82bf0c4ef4fcdc570ea2e1e92176e5c848b6413545b885db49101611483565b6001600160a01b03818116600090815260146020526040902054163314611aba5760405162461bcd60e51b815260206004820152601f60248201527f6f6e6c792070726f706f736564207061796565732063616e20616363657074006044820152606401610c30565b6001600160a01b0381811660008181526013602090815260408083208054337fffffffffffffffffffffffff000000000000000000000000000000000000000080831682179093556014909452828520805490921690915590519416939092849290917f78af32efdcad432315431e9b03d27e6cd98fb79c405fdc5af7c1714d9c0f75b39190a45050565b60005a604080516101008082018352600b5460ff8116835290810464ffffffffff90811660208085018290526601000000000000840463ffffffff908116968601969096526a01000000000000000000008404861660608601526e01000000000000000000000000000084048616608086015272010000000000000000000000000000000000008404861660a0860152760100000000000000000000000000000000000000000000840490951660c08501527a01000000000000000000000000000000000000000000000000000090920462ffffff1660e08401529394509092918c013591821611611c795760405162461bcd60e51b815260206004820152600c60248201527f7374616c65207265706f727400000000000000000000000000000000000000006044820152606401610c30565b3360009081526002602052604090205460ff16611cd85760405162461bcd60e51b815260206004820152601860248201527f756e617574686f72697a6564207472616e736d697474657200000000000000006044820152606401610c30565b600a548b3514611d2a5760405162461bcd60e51b815260206004820152601560248201527f636f6e666967446967657374206d69736d6174636800000000000000000000006044820152606401610c30565b611d388a8a8a8a8a8a613b05565b8151611d4590600161530d565b60ff168714611d965760405162461bcd60e51b815260206004820152601a60248201527f77726f6e67206e756d626572206f66207369676e6174757265730000000000006044820152606401610c30565b868514611de55760405162461bcd60e51b815260206004820152601e60248201527f7369676e617475726573206f7574206f6620726567697374726174696f6e00006044820152606401610c30565b60008a8a604051611df7929190615326565b604051908190038120611e0e918e90602001615336565b60408051601f19818403018152828252805160209182012083830190925260008084529083018190529092509060005b8a811015611fb45760006001858a8460208110611e5d57611e5d615192565b611e6a91901a601b61530d565b8f8f86818110611e7c57611e7c615192565b905060200201358e8e87818110611e9557611e95615192565b9050602002013560405160008152602001604052604051611ed2949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015611ef4573d6000803e3d6000fd5b505060408051601f198101516001600160a01b03811660009081526003602090815290849020838501909452925460ff8082161515808552610100909204169383019390935290955092509050611f8d5760405162461bcd60e51b815260206004820152600f60248201527f7369676e6174757265206572726f7200000000000000000000000000000000006044820152606401610c30565b826020015160080260ff166001901b84019350508080611fac906152d5565b915050611e3e565b5081827e0101010101010101010101010101010101010101010101010101010101010116146120255760405162461bcd60e51b815260206004820152601060248201527f6475706c6963617465207369676e6572000000000000000000000000000000006044820152606401610c30565b50600091506120749050838d836020020135848e8e8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613ba292505050565b90506120828382863361409f565b505050505050505050505050565b60006120d3336000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061112792505050565b61211f5760405162461bcd60e51b815260206004820152600960248201527f4e6f2061636365737300000000000000000000000000000000000000000000006044820152606401610c30565b612128826141ea565b90505b919050565b6000612173336000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061112792505050565b6121bf5760405162461bcd60e51b815260206004820152600960248201527f4e6f2061636365737300000000000000000000000000000000000000000000006044820152606401610c30565b6121288261421c565b6000546001600160a01b031633148061226b57506012546040517f6b14daf80000000000000000000000000000000000000000000000000000000081526001600160a01b0390911690636b14daf89061222a9033906000903690600401615279565b602060405180830381865afa158015612247573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061226b9190615257565b6122b75760405162461bcd60e51b815260206004820181905260248201527f4f6e6c79206f776e65722662696c6c696e6741646d696e2063616e2063616c6c6044820152606401610c30565b60006122c161426e565b6011546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529192506000916001600160a01b03909116906370a0823190602401602060405180830381865afa158015612328573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061234c919061523e565b90508181101561239e5760405162461bcd60e51b815260206004820152601460248201527f696e73756666696369656e742062616c616e63650000000000000000000000006044820152606401610c30565b6011546001600160a01b031663a9059cbb856123c36123bd868661534c565b8761444f565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b1681526001600160a01b03909216600483015260248201526044016020604051808303816000875af1158015612426573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061244a9190615257565b6124965760405162461bcd60e51b815260206004820152601260248201527f696e73756666696369656e742066756e647300000000000000000000000000006044820152606401610c30565b50505050565b6011546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009182916001600160a01b03909116906370a0823190602401602060405180830381865afa158015612502573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612526919061523e565b9050600061253261426e565b905061253e818361535f565b9250505090565b61254d613308565b601f8651111561259f5760405162461bcd60e51b815260206004820152601060248201527f746f6f206d616e79206f7261636c6573000000000000000000000000000000006044820152606401610c30565b84518651146125f05760405162461bcd60e51b815260206004820152601660248201527f6f7261636c65206c656e677468206d69736d61746368000000000000000000006044820152606401610c30565b85516125fd85600361537f565b60ff161061264d5760405162461bcd60e51b815260206004820152601860248201527f6661756c74792d6f7261636c65206620746f6f206869676800000000000000006044820152606401610c30565b6126598460ff16614466565b604080517f010000000000000000000000000000000000000000000000000000000000000060208201527f0000000000000000000000000000000000000000000000000000000000000001821b60218201527f00000000000000000000ffffffffffffffffffffffffffffffffffffffffffff90911b6039820152605101604051602081830303815290604052805190602001208380519060200120146127425760405162461bcd60e51b815260206004820152601560248201527f696e76616c6964206f6e636861696e436f6e66696700000000000000000000006044820152606401610c30565b6040805160c0810182528781526020810187905260ff8616918101919091526060810184905267ffffffffffffffff8316608082015260a08101829052600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000ff1690556127af613362565b60045460005b8181101561288e576000600482815481106127d2576127d2615192565b6000918252602082200154600580546001600160a01b03909216935090849081106127ff576127ff615192565b60009182526020808320909101546001600160a01b03948516835260038252604080842080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016905594168252600290529190912080547fffffffffffffffffffffffffffffffffffff00000000000000000000000000001690555080612886816152d5565b9150506127b5565b5061289b600460006149bf565b6128a7600560006149bf565b60005b825151811015612bb45760036000846000015183815181106128ce576128ce615192565b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff16156129425760405162461bcd60e51b815260206004820152601760248201527f7265706561746564207369676e657220616464726573730000000000000000006044820152606401610c30565b604080518082019091526001815260ff82166020820152835180516003916000918590811061297357612973615192565b6020908102919091018101516001600160a01b0316825281810192909252604001600090812083518154948401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009095169015157fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff161761010060ff90951694909402939093179092558401518051600292919084908110612a1857612a18615192565b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff1615612a8c5760405162461bcd60e51b815260206004820152601c60248201527f7265706561746564207472616e736d69747465722061646472657373000000006044820152606401610c30565b60405180606001604052806001151581526020018260ff16815260200160006bffffffffffffffffffffffff168152506002600085602001518481518110612ad657612ad6615192565b6020908102919091018101516001600160a01b03168252818101929092526040908101600020835181549385015194909201516bffffffffffffffffffffffff1662010000027fffffffffffffffffffffffffffffffffffff000000000000000000000000ffff60ff95909516610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff931515939093167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090941693909317919091179290921617905580612bac816152d5565b9150506128aa565b5081518051612bcb916004916020909101906149dd565b506020808301518051612be29260059201906149dd565b506040820151600b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff909216919091179055600d80547fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff811664010000000063ffffffff438116820292831785559083048116936001939092600092612c749286929082169116176152b8565b92506101000a81548163ffffffff021916908363ffffffff160217905550612cd34630600d60009054906101000a900463ffffffff1663ffffffff1686600001518760200151886040015189606001518a608001518b60a001516144b6565b600a819055600d5484516020860151604080880151606089015160808a015160a08b015193517f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0598612d3c988b98919763ffffffff90911696919590949093909290919061539b565b60405180910390a1600b546601000000000000900463ffffffff1660005b845151811015612db45781600682601f8110612d7857612d78615192565b600891828204019190066004026101000a81548163ffffffff021916908363ffffffff1602179055508080612dac906152d5565b915050612d5a565b5050505050505050505050565b6001600160a01b03811660009081526002602090815260408083208151606081018352905460ff80821615158084526101008304909116948301949094526201000090046bffffffffffffffffffffffff169181019190915290612e285750600092915050565b6006816020015160ff16601f8110612e4257612e42615192565b600881049190910154600b54612e78926007166004026101000a90910463ffffffff9081169166010000000000009004166151f0565b9392505050565b600080808080333214612ed45760405162461bcd60e51b815260206004820152601460248201527f4f6e6c792063616c6c61626c6520627920454f410000000000000000000000006044820152606401610c30565b5050600a54600b5463ffffffff6601000000000000820481166000908152600c60205260409020549296610100909204600881901c8216965064ffffffffff169450601783900b93507c010000000000000000000000000000000000000000000000000000000090920490911690565b612f4c613308565b60408051808201909152600e546001600160a01b038082168084527401000000000000000000000000000000000000000090920463ffffffff1660208401528416141580612faa57508163ffffffff16816020015163ffffffff1614155b1561305c576040805180820182526001600160a01b0385811680835263ffffffff8681166020948501819052600e80547fffffffffffffffff00000000000000000000000000000000000000000000000016841774010000000000000000000000000000000000000000830217905586518786015187519316835294820152909392909116917fb04e3a37abe9c0fcdfebdeae019a8e2b12ddf53f5d55ffb0caccc1bedaca1541910160405180910390a35b505050565b6001600160a01b038281166000908152601360205260409020541633146130ca5760405162461bcd60e51b815260206004820152601d60248201527f6f6e6c792063757272656e742070617965652063616e207570646174650000006044820152606401610c30565b6001600160a01b03811633036131225760405162461bcd60e51b815260206004820152601760248201527f63616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610c30565b6001600160a01b03808316600090815260146020526040902080548383167fffffffffffffffffffffffff00000000000000000000000000000000000000008216811790925590911690811461305c576040516001600160a01b038084169133918616907f84f7c7c80bb8ed2279b4aab5f61cd05e6374073d38f46d7f32de8c30e9e3836790600090a4505050565b6131b9613308565b61148c81614544565b6131ca613308565b61148c81614605565b600080600080600061321c336000368080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061112792505050565b6132685760405162461bcd60e51b815260206004820152600960248201527f4e6f2061636365737300000000000000000000000000000000000000000000006044820152606401610c30565b6132f7600b546601000000000000900463ffffffff9081166000818152600c602090815260409182902082516060810184529054601781900b8083527801000000000000000000000000000000000000000000000000820487169383018490527c0100000000000000000000000000000000000000000000000000000000909104909516920182905291938490565b945094509450945094509091929394565b6000546001600160a01b031633146108e25760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610c30565b601154600b54604080516103e08101918290526001600160a01b0390931692660100000000000090920463ffffffff1691600091600690601f908285855b82829054906101000a900463ffffffff1663ffffffff16815260200190600401906020826003010492830192600103820291508084116133a0579050505050505090506000600580548060200260200160405190810160405280929190818152602001828054801561343b57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161341d575b5050505050905060005b81518110156137385760006002600084848151811061346657613466615192565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060000160029054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff1690506000600260008585815181106134d2576134d2615192565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060000160026101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff16021790555060008483601f811061353f5761353f615192565b6020020151600b5490870363ffffffff90811692507201000000000000000000000000000000000000909104168102633b9aca00028201801561372d5760006013600087878151811061359457613594615192565b6020908102919091018101516001600160a01b0390811683529082019290925260409081016000205490517fa9059cbb00000000000000000000000000000000000000000000000000000000815290821660048201819052602482018590529250908a169063a9059cbb906044016020604051808303816000875af1158015613621573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136459190615257565b6136915760405162461bcd60e51b815260206004820152601260248201527f696e73756666696369656e742066756e647300000000000000000000000000006044820152606401610c30565b878786601f81106136a4576136a4615192565b602002019063ffffffff16908163ffffffff1681525050886001600160a01b0316816001600160a01b03168787815181106136e1576136e1615192565b60200260200101516001600160a01b03167fd0b1dac935d85bd54cf0a33b0d41d39f8cf53a968465fc7ea2377526b8ac712c8560405161372391815260200190565b60405180910390a4505b505050600101613445565b50611919600683601f614a5a565b6001600160a01b03821660009081526016602052604081205460ff168061114657505060155460ff161592915050565b60606010805461378590615431565b80601f01602080910402602001604051908101604052809291908181526020018280546137b190615431565b80156110765780601f106137d357610100808354040283529160200191611076565b820191906000526020600020905b8154815290600101906020018083116137e157509395945050505050565b6001600160a01b0381166000908152600260209081526040918290208251606081018452905460ff80821615158084526101008304909116938301939093526201000090046bffffffffffffffffffffffff1692810192909252613861575050565b600061386c836108e4565b9050801561305c576001600160a01b03838116600090815260136020526040908190205460115491517fa9059cbb000000000000000000000000000000000000000000000000000000008152908316600482018190526024820185905292919091169063a9059cbb906044016020604051808303816000875af11580156138f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061391b9190615257565b6139675760405162461bcd60e51b815260206004820152601260248201527f696e73756666696369656e742066756e647300000000000000000000000000006044820152606401610c30565b600b60000160069054906101000a900463ffffffff166006846020015160ff16601f811061399757613997615192565b6008810491909101805460079092166004026101000a63ffffffff8181021990931693909216919091029190911790556001600160a01b0384811660008181526002602090815260409182902080547fffffffffffffffffffffffffffffffffffff000000000000000000000000ffff169055601154915186815291841693851692917fd0b1dac935d85bd54cf0a33b0d41d39f8cf53a968465fc7ea2377526b8ac712c910160405180910390a450505050565b60008080808063ffffffff69ffffffffffffffffffff87161115613a7d57506000935083925082915081905080611721565b5050505063ffffffff8281166000908152600c602090815260409182902082516060810184529054601781900b8083527801000000000000000000000000000000000000000000000000820486169383018490527c01000000000000000000000000000000000000000000000000000000009091049094169201829052939491939250908490565b6000613b12826020615214565b613b1d856020615214565b613b298861014461522b565b613b33919061522b565b613b3d919061522b565b613b4890600061522b565b9050368114613b995760405162461bcd60e51b815260206004820152601860248201527f63616c6c64617461206c656e677468206d69736d6174636800000000000000006044820152606401610c30565b50505050505050565b600080613bae8361468c565b9050601f8160400151511115613c065760405162461bcd60e51b815260206004820152601e60248201527f6e756d206f62736572766174696f6e73206f7574206f6620626f756e647300006044820152606401610c30565b604081015151865160ff1610613c5e5760405162461bcd60e51b815260206004820152601e60248201527f746f6f206665772076616c75657320746f207472757374206d656469616e00006044820152606401610c30565b64ffffffffff841660208701526040810151805160009190613c829060029061547e565b81518110613c9257613c92615192565b602002602001015190508060170b7f000000000000000000000000000000000000000000000000000000000000000160170b13158015613cf857507f00000000000000000000ffffffffffffffffffffffffffffffffffffffffffff60170b8160170b13155b613d445760405162461bcd60e51b815260206004820152601e60248201527f6d656469616e206973206f7574206f66206d696e2d6d61782072616e676500006044820152606401610c30565b60408701805190613d54826154b9565b63ffffffff1663ffffffff168152505060405180606001604052808260170b8152602001836000015163ffffffff1681526020014263ffffffff16815250600c6000896040015163ffffffff1663ffffffff16815260200190815260200160002060008201518160000160006101000a81548177ffffffffffffffffffffffffffffffffffffffffffffffff021916908360170b77ffffffffffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160186101000a81548163ffffffff021916908363ffffffff160217905550604082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555090505086600b60008201518160000160006101000a81548160ff021916908360ff16021790555060208201518160000160016101000a81548164ffffffffff021916908364ffffffffff16021790555060408201518160000160066101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001600a6101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600e6101000a81548163ffffffff021916908363ffffffff16021790555060a08201518160000160126101000a81548163ffffffff021916908363ffffffff16021790555060c08201518160000160166101000a81548163ffffffff021916908363ffffffff16021790555060e082015181600001601a6101000a81548162ffffff021916908362ffffff160217905550905050866040015163ffffffff167fc797025feeeaf2cd924c99e9205acb8ec04d5cad21c41ce637a38fb6dee6016a823385600001518660400151876020015188606001518d8d604051613fe89897969594939291906154dc565b60405180910390a26040808801518351915163ffffffff9283168152600092909116907f0109fc6f55cf40689f02fbaad7af7fe7bbac8a3d2186600afc7d3e10cac602719060200160405180910390a3866040015163ffffffff168160170b7f0559884fd3a460db3073b7fc896cc77986f16e378210ded43186175bf646fc5f4260405161407891815260200190565b60405180910390a361409187604001518260170b614731565b506060015195945050505050565b60008360170b126124965760006140d1633b9aca003a04866080015163ffffffff16876060015163ffffffff16614881565b90506010360260005a905060006140fa8663ffffffff1685858b60e0015162ffffff16866148a7565b90506000670de0b6b3a764000077ffffffffffffffffffffffffffffffffffffffffffffffff891683026001600160a01b03881660009081526002602052604090205460c08c01519290910492506201000090046bffffffffffffffffffffffff9081169163ffffffff16633b9aca0002828401019081168211156141855750505050505050612496565b6001600160a01b038816600090815260026020526040902080546bffffffffffffffffffffffff90921662010000027fffffffffffffffffffffffffffffffffffff000000000000000000000000ffff90921691909117905550505050505050505050565b600063ffffffff82111561420057506000919050565b5063ffffffff166000908152600c602052604090205460170b90565b600063ffffffff82111561423257506000919050565b5063ffffffff9081166000908152600c60205260409020547c010000000000000000000000000000000000000000000000000000000090041690565b60008060058054806020026020016040519081016040528092919081815260200182805480156142c757602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116142a9575b50508351600b54604080516103e08101918290529697509195660100000000000090910463ffffffff169450600093509150600690601f908285855b82829054906101000a900463ffffffff1663ffffffff16815260200190600401906020826003010492830192600103820291508084116143035790505050505050905060005b83811015614396578181601f811061436357614363615192565b602002015161437290846151f0565b6143829063ffffffff168761522b565b95508061438e816152d5565b915050614349565b50600b546143c4907201000000000000000000000000000000000000900463ffffffff16633b9aca00615214565b6143ce9086615214565b945060005b8381101561444757600260008683815181106143f1576143f1615192565b6020908102919091018101516001600160a01b0316825281019190915260400160002054614433906201000090046bffffffffffffffffffffffff168761522b565b95508061443f816152d5565b9150506143d3565b505050505090565b600081831015614460575081611149565b50919050565b8060001061148c5760405162461bcd60e51b815260206004820152601260248201527f66206d75737420626520706f73697469766500000000000000000000000000006044820152606401610c30565b6000808a8a8a8a8a8a8a8a8a6040516020016144da99989796959493929190615584565b60408051601f1981840301815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179150505b9998505050505050505050565b336001600160a01b0382160361459c5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610c30565b600180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6012546001600160a01b039081169082168114610ca157601280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0384811691821790925560408051928416835260208301919091527f793cb73064f3c8cde7e187ae515511e6e56d1ee89bf08b82fa60fb70f8d4891291016119ab565b6146c06040518060800160405280600063ffffffff1681526020016060815260200160608152602001600060170b81525090565b60008060606000858060200190518101906146db919061561e565b929650909450925090506146ef868361490b565b81516040805160208082019690965281519082018252918252805160808101825263ffffffff969096168652938501529183015260170b606082015292915050565b60408051808201909152600e546001600160a01b0381168083527401000000000000000000000000000000000000000090910463ffffffff16602083015261477857505050565b60006147856001856151f0565b63ffffffff8181166000818152600c6020908152604091829020549087015187519251602481019490945260179190910b6044840181905289851660648501526084840189905294955061483593169160a40160408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fbeed9b5100000000000000000000000000000000000000000000000000000000179052614983565b6119195760405162461bcd60e51b815260206004820152601060248201527f696e73756666696369656e7420676173000000000000000000000000000000006044820152606401610c30565b6000838381101561489457600285850304015b61489e818461444f565b95945050505050565b6000818610156148f95760405162461bcd60e51b815260206004820181905260248201527f6c6566744761732063616e6e6f742065786365656420696e697469616c4761736044820152606401610c30565b50633b9aca0094039190910101020290565b60008151602061491b9190615214565b6149269060a061522b565b61493190600061522b565b90508083511461305c5760405162461bcd60e51b815260206004820152601660248201527f7265706f7274206c656e677468206d69736d61746368000000000000000000006044820152606401610c30565b60005a61138881106149b757611388810390508460408204820311156149b7576000808451602086016000888af150600191505b509392505050565b508054600082559060005260206000209081019061148c9190614aed565b828054828255906000526020600020908101928215614a4a579160200282015b82811115614a4a57825182547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b039091161782556020909201916001909101906149fd565b50614a56929150614aed565b5090565b600483019183908215614a4a5791602002820160005b83821115614ab457835183826101000a81548163ffffffff021916908363ffffffff1602179055509260200192600401602081600301049283019260010302614a70565b8015614ae45782816101000a81549063ffffffff0219169055600401602081600301049283019260010302614ab4565b5050614a569291505b5b80821115614a565760008155600101614aee565b6001600160a01b038116811461148c57600080fd5b600060208284031215614b2957600080fd5b8135612e7881614b02565b6000815180845260005b81811015614b5a57602081850181015186830182015201614b3e565b506000602082860101526020601f19601f83011685010191505092915050565b6020815260006111466020830184614b34565b60008060408385031215614ba057600080fd5b8235614bab81614b02565b91506020830135614bbb81614b02565b809150509250929050565b63ffffffff8116811461148c57600080fd5b600080600080600060a08688031215614bf057600080fd5b8535614bfb81614bc6565b94506020860135614c0b81614bc6565b93506040860135614c1b81614bc6565b92506060860135614c2b81614bc6565b9150608086013562ffffff81168114614c4357600080fd5b809150509295509295909350565b600081518084526020808501945080840160005b83811015614c8a5781516001600160a01b031687529582019590820190600101614c65565b509495945050505050565b6020815260006111466020830184614c51565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715614d0057614d00614ca8565b604052919050565b600082601f830112614d1957600080fd5b813567ffffffffffffffff811115614d3357614d33614ca8565b614d466020601f19601f84011601614cd7565b818152846020838601011115614d5b57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215614d8b57600080fd5b8235614d9681614b02565b9150602083013567ffffffffffffffff811115614db257600080fd5b614dbe85828601614d08565b9150509250929050565b600060208284031215614dda57600080fd5b813569ffffffffffffffffffff81168114612e7857600080fd5b60008083601f840112614e0657600080fd5b50813567ffffffffffffffff811115614e1e57600080fd5b6020830191508360208260051b8501011115614e3957600080fd5b9250929050565b60008060008060408587031215614e5657600080fd5b843567ffffffffffffffff80821115614e6e57600080fd5b614e7a88838901614df4565b90965094506020870135915080821115614e9357600080fd5b50614ea087828801614df4565b95989497509550505050565b60008060008060008060008060e0898b031215614ec857600080fd5b606089018a811115614ed957600080fd5b8998503567ffffffffffffffff80821115614ef357600080fd5b818b0191508b601f830112614f0757600080fd5b813581811115614f1657600080fd5b8c6020828501011115614f2857600080fd5b6020830199508098505060808b0135915080821115614f4657600080fd5b614f528c838d01614df4565b909750955060a08b0135915080821115614f6b57600080fd5b50614f788b828c01614df4565b999c989b50969995989497949560c00135949350505050565b600060208284031215614fa357600080fd5b5035919050565b60008060408385031215614fbd57600080fd5b8235614fc881614b02565b946020939093013593505050565b600067ffffffffffffffff821115614ff057614ff0614ca8565b5060051b60200190565b600082601f83011261500b57600080fd5b8135602061502061501b83614fd6565b614cd7565b82815260059290921b8401810191818101908684111561503f57600080fd5b8286015b8481101561506357803561505681614b02565b8352918301918301615043565b509695505050505050565b803560ff8116811461212b57600080fd5b803567ffffffffffffffff8116811461212b57600080fd5b60008060008060008060c087890312156150b057600080fd5b863567ffffffffffffffff808211156150c857600080fd5b6150d48a838b01614ffa565b975060208901359150808211156150ea57600080fd5b6150f68a838b01614ffa565b965061510460408a0161506e565b9550606089013591508082111561511a57600080fd5b6151268a838b01614d08565b945061513460808a0161507f565b935060a089013591508082111561514a57600080fd5b5061515789828a01614d08565b9150509295509295509295565b6000806040838503121561517757600080fd5b823561518281614b02565b91506020830135614bbb81614bc6565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b63ffffffff82811682821603908082111561520d5761520d6151c1565b5092915050565b8082028115828204841417611149576111496151c1565b80820180821115611149576111496151c1565b60006020828403121561525057600080fd5b5051919050565b60006020828403121561526957600080fd5b81518015158114612e7857600080fd5b6001600160a01b038416815260406020820152816040820152818360608301376000818301606090810191909152601f909201601f1916010192915050565b63ffffffff81811683821601908082111561520d5761520d6151c1565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615306576153066151c1565b5060010190565b60ff8181168382160190811115611149576111496151c1565b8183823760009101908152919050565b8281526080810160608360208401379392505050565b81810381811115611149576111496151c1565b818103600083128015838313168383128216171561520d5761520d6151c1565b60ff818116838216029081169081811461520d5761520d6151c1565b600061012063ffffffff808d1684528b6020850152808b166040850152508060608401526153cb8184018a614c51565b905082810360808401526153df8189614c51565b905060ff871660a084015282810360c08401526153fc8187614b34565b905067ffffffffffffffff851660e08401528281036101008401526154218185614b34565b9c9b505050505050505050505050565b600181811c9082168061544557607f821691505b602082108103614460577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000826154b4577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600063ffffffff8083168181036154d2576154d26151c1565b6001019392505050565b600061010080830160178c810b855260206001600160a01b038d168187015263ffffffff8c1660408701528360608701528293508a5180845261012087019450818c01935060005b81811015615542578451840b86529482019493820193600101615524565b505050505082810360808401526155598188614b34565b91505061556b60a083018660170b9052565b8360c083015261453760e083018464ffffffffff169052565b60006101208b83526001600160a01b038b16602084015267ffffffffffffffff808b1660408501528160608501526155be8285018b614c51565b915083820360808501526155d2828a614c51565b915060ff881660a085015283820360c08501526155ef8288614b34565b90861660e085015283810361010085015290506154218185614b34565b8051601781900b811461212b57600080fd5b6000806000806080858703121561563457600080fd5b845161563f81614bc6565b809450506020808601519350604086015167ffffffffffffffff81111561566557600080fd5b8601601f8101881361567657600080fd5b805161568461501b82614fd6565b81815260059190911b8201830190838101908a8311156156a357600080fd5b928401925b828410156156c8576156b98461560c565b825292840192908401906156a8565b80965050505050506156dc6060860161560c565b90509295919450925056fe416363657373436f6e74726f6c6c65644f43523241676772656761746f7220312e302e30a2646970667358221220fed0cd68c5bfb721dbfe295c92e43bb48a83a2d5f53ba8e3528a83638fb3c6ad64736f6c63430008130033

Verified Source Code Full Match

Compiler: v0.8.19+commit.7dd6d404 EVM: paris Optimization: Yes (10000 runs)
OCR2Abstract.sol 141 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./interfaces/TypeAndVersionInterface.sol";


abstract contract OCR2Abstract is TypeAndVersionInterface {
  // Maximum number of oracles the offchain reporting protocol is designed for
  uint256 constant internal maxNumOracles = 31;

  /**
   * @notice triggers a new run of the offchain reporting protocol
   * @param previousConfigBlockNumber block in which the previous config was set, to simplify historic analysis
   * @param configDigest configDigest of this configuration
   * @param configCount ordinal number of this config setting among all config settings over the life of this contract
   * @param signers ith element is address ith oracle uses to sign a report
   * @param transmitters ith element is address ith oracle uses to transmit a report via the transmit method
   * @param f maximum number of faulty/dishonest oracles the protocol can tolerate while still working correctly
   * @param onchainConfig serialized configuration used by the contract (and possibly oracles)
   * @param offchainConfigVersion version of the serialization format used for "offchainConfig" parameter
   * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract
   */
  event ConfigSet(
    uint32 previousConfigBlockNumber,
    bytes32 configDigest,
    uint64 configCount,
    address[] signers,
    address[] transmitters,
    uint8 f,
    bytes onchainConfig,
    uint64 offchainConfigVersion,
    bytes offchainConfig
  );

  /**
   * @notice sets offchain reporting protocol configuration incl. participating oracles
   * @param signers addresses with which oracles sign the reports
   * @param transmitters addresses oracles use to transmit the reports
   * @param f number of faulty oracles the system can tolerate
   * @param onchainConfig serialized configuration used by the contract (and possibly oracles)
   * @param offchainConfigVersion version number for offchainEncoding schema
   * @param offchainConfig serialized configuration used by the oracles exclusively and only passed through the contract
   */
  function setConfig(
    address[] memory signers,
    address[] memory transmitters,
    uint8 f,
    bytes memory onchainConfig,
    uint64 offchainConfigVersion,
    bytes memory offchainConfig
  )
    external
    virtual;

  /**
   * @notice information about current offchain reporting protocol configuration
   * @return configCount ordinal number of current config, out of all configs applied to this contract so far
   * @return blockNumber block at which this config was set
   * @return configDigest domain-separation tag for current config (see _configDigestFromConfigData)
   */
  function latestConfigDetails()
    external
    view
    virtual
    returns (
      uint32 configCount,
      uint32 blockNumber,
      bytes32 configDigest
    );

  function _configDigestFromConfigData(
    uint256 chainId,
    address contractAddress,
    uint64 configCount,
    address[] memory signers,
    address[] memory transmitters,
    uint8 f,
    bytes memory onchainConfig,
    uint64 offchainConfigVersion,
    bytes memory offchainConfig
  )
    internal
    pure
    returns (bytes32)
  {
    uint256 h = uint256(keccak256(abi.encode(chainId, contractAddress, configCount,
      signers, transmitters, f, onchainConfig, offchainConfigVersion, offchainConfig
    )));
    uint256 prefixMask = type(uint256).max << (256-16); // 0xFFFF00..00
    uint256 prefix = 0x0001 << (256-16); // 0x000100..00
    return bytes32((prefix & prefixMask) | (h & ~prefixMask));
  }

  /**
  * @notice optionally emitted to indicate the latest configDigest and epoch for
     which a report was successfully transmitted. Alternatively, the contract may
     use latestConfigDigestAndEpoch with scanLogs set to false.
  */
  event Transmitted(
    bytes32 configDigest,
    uint32 epoch
  );

  /**
   * @notice optionally returns the latest configDigest and epoch for which a
     report was successfully transmitted. Alternatively, the contract may return
     scanLogs set to true and use Transmitted events to provide this information
     to offchain watchers.
   * @return scanLogs indicates whether to rely on the configDigest and epoch
     returned or whether to scan logs for the Transmitted event instead.
   * @return configDigest
   * @return epoch
   */
  function latestConfigDigestAndEpoch()
    external
    view
    virtual
    returns(
      bool scanLogs,
      bytes32 configDigest,
      uint32 epoch
    );

  /**
   * @notice transmit is called to post a new report to the contract
   * @param reportContext serialized report context containing configDigest, epoch, round, extraHash
   * @param report serialized report, which the signatures are signing
   * @param rs ith element is the R components of the ith signature on report. Must have at most maxNumOracles entries
   * @param ss ith element is the S components of the ith signature on report. Must have at most maxNumOracles entries
   * @param rawVs ith element is the the V component of the ith signature
   */
  function transmit(
    // NOTE: If these parameters are changed, expectedMsgDataLength and/or
    // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly
    bytes32[3] calldata reportContext,
    bytes calldata report,
    bytes32[] calldata rs, bytes32[] calldata ss, bytes32 rawVs // signatures
  )
    external
    virtual;
}
ConfirmedOwner.sol 22 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./ConfirmedOwnerWithProposal.sol";

/**
 * @title The ConfirmedOwner contract
 * @notice A contract with helpers for basic contract ownership.
 */
contract ConfirmedOwner is ConfirmedOwnerWithProposal {

  constructor(
    address newOwner
  )
    ConfirmedOwnerWithProposal(
      newOwner,
      address(0)
    )
  {
  }

}
OCR2Aggregator.sol 1623 lines
// SPDX-License-Identifier: MIT
pragma solidity =0.8.19;

import "./interfaces/AccessControllerInterface.sol";
import "./interfaces/AggregatorV2V3Interface.sol";
import "./interfaces/AggregatorValidatorInterface.sol";
import "./interfaces/LinkTokenInterface.sol";
import "./interfaces/TypeAndVersionInterface.sol";
import "./OCR2Abstract.sol";
import "./OwnerIsCreator.sol";


/**
 * @notice OCR2Aggregator for numerical data with billing support.

 * @dev
 * If you read or change this, be sure to read or adjust the comments. They
 * track the units of the values under consideration, and are crucial to
 * the readability of the operations it specifies.

 * @notice
 * Billing Trust Model:

 * Nothing in this contract prevents a billing admin from setting insane
 * values for the billing parameters in setBilling. Oracles
 * participating in this contract should regularly check that the
 * parameters make sense. Similarly, the outstanding obligations of this
 * contract to the oracles can exceed the funds held by the contract.
 * Oracles participating in this contract should regularly check that it
 * holds sufficient funds and stop interacting with it if funding runs
 * out.

 * This still leaves oracles with some risk due to TOCTOU issues.
 * However, since the sums involved are pretty small (Ethereum
 * transactions aren't that expensive in the end) and an oracle would
 * likely stop participating in a contract it repeatedly lost money on,
 * this risk is deemed acceptable. Oracles should also regularly
 * withdraw any funds in the contract to prevent issues where the
 * contract becomes underfunded at a later time, and different oracles
 * are competing for the left-over funds.

 * Finally, note that any change to the set of oracles or to the billing
 * parameters will trigger payout of all oracles first (using the old
 * parameters), a billing admin cannot take away funds that are already
 * marked for payment.
 */
contract OCR2Aggregator is OCR2Abstract, OwnerIsCreator, AggregatorV2V3Interface {
  // This contract is divided into sections. Each section defines a set of
  // variables, events, and functions that belong together.

  /***************************************************************************
   * Section: Variables used in multiple other sections
   **************************************************************************/

  struct Transmitter {
    bool active;

    // Index of oracle in s_signersList/s_transmittersList
    uint8 index;

    // juels-denominated payment for transmitters, covering gas costs incurred
    // by the transmitter plus additional rewards. The entire LINK supply (1e9
    // LINK = 1e27 Juels) will always fit into a uint96.
    uint96 paymentJuels;
  }
  mapping (address /* transmitter address */ => Transmitter) internal s_transmitters;

  struct Signer {
    bool active;

    // Index of oracle in s_signersList/s_transmittersList
    uint8 index;
  }
  mapping (address /* signer address */ => Signer) internal s_signers;

  // s_signersList contains the signing address of each oracle
  address[] internal s_signersList;

  // s_transmittersList contains the transmission address of each oracle,
  // i.e. the address the oracle actually sends transactions to the contract from
  address[] internal s_transmittersList;

  // We assume that all oracles contribute observations to all rounds. this
  // variable tracks (per-oracle) from what round an oracle should be rewarded,
  // i.e. the oracle gets (latestAggregatorRoundId -
  // rewardFromAggregatorRoundId) * reward
  uint32[maxNumOracles] internal s_rewardFromAggregatorRoundId;

  bytes32 s_latestConfigDigest;

  // Storing these fields used on the hot path in a HotVars variable reduces the
  // retrieval of all of them to a single SLOAD.
  struct HotVars {
    // maximum number of faulty oracles
    uint8 f;

    // epoch and round from OCR protocol.
    // 32 most sig bits for epoch, 8 least sig bits for round
    uint40 latestEpochAndRound;

    // Chainlink Aggregators expose a roundId to consumers. The offchain reporting
    // protocol does not use this id anywhere. We increment it whenever a new
    // transmission is made to provide callers with contiguous ids for successive
    // reports.
    uint32 latestAggregatorRoundId;

    // Highest compensated gas price, in gwei uints
    uint32 maximumGasPriceGwei;

    // If gas price is less (in gwei units), transmitter gets half the savings
    uint32 reasonableGasPriceGwei;

    // Fixed LINK reward for each observer
    uint32 observationPaymentGjuels;

    // Fixed reward for transmitter
    uint32 transmissionPaymentGjuels;

    // Overhead incurred by accounting logic
    uint24 accountingGas;
  }
  HotVars internal s_hotVars;

  // Transmission records the median answer from the transmit transaction at
  // time timestamp
  struct Transmission {
    int192 answer; // 192 bits ought to be enough for anyone
    uint32 observationsTimestamp; // when were observations made offchain
    uint32 transmissionTimestamp; // when was report received onchain
  }
  mapping(uint32 /* aggregator round ID */ => Transmission) internal s_transmissions;

  // Lowest answer the system is allowed to report in response to transmissions
  int192 immutable public minAnswer;
  // Highest answer the system is allowed to report in response to transmissions
  int192 immutable public maxAnswer;

  /***************************************************************************
   * Section: Constructor
   **************************************************************************/

  /**
   * @param link address of the LINK contract
   * @param minAnswer_ lowest answer the median of a report is allowed to be
   * @param maxAnswer_ highest answer the median of a report is allowed to be
   * @param requesterAccessController access controller for requesting new rounds
   * @param decimals_ answers are stored in fixed-point format, with this many digits of precision
   * @param description_ short human-readable description of observable this contract's answers pertain to
   */
  constructor(
    LinkTokenInterface link,
    int192 minAnswer_,
    int192 maxAnswer_,
    AccessControllerInterface billingAccessController,
    AccessControllerInterface requesterAccessController,
    uint8 decimals_,
    string memory description_
  ) {
    s_linkToken = link;
    emit LinkTokenSet(LinkTokenInterface(address(0)), link);
    _setBillingAccessController(billingAccessController);

    decimals = decimals_;
    s_description = description_;
    setRequesterAccessController(requesterAccessController);
    setValidatorConfig(AggregatorValidatorInterface(address(0x0)), 0);
    minAnswer = minAnswer_;
    maxAnswer = maxAnswer_;
  }


  /***************************************************************************
   * Section: OCR2Abstract Configuration
   **************************************************************************/

  // incremented each time a new config is posted. This count is incorporated
  // into the config digest to prevent replay attacks.
  uint32 internal s_configCount;

  // makes it easier for offchain systems to extract config from logs
  uint32 internal s_latestConfigBlockNumber;

  // left as a function so this check can be disabled in derived contracts
  function _requirePositiveF (
    uint256 f
  )
    internal
    pure
    virtual
  {
    require(0 < f, "f must be positive");
  }

  struct SetConfigArgs {
    address[] signers;
    address[] transmitters;
    uint8 f;
    bytes onchainConfig;
    uint64 offchainConfigVersion;
    bytes offchainConfig;
  }

  /// @inheritdoc OCR2Abstract
  function setConfig(
    address[] memory signers,
    address[] memory transmitters,
    uint8 f,
    bytes memory onchainConfig,
    uint64 offchainConfigVersion,
    bytes memory offchainConfig
  )
    external
    override
    onlyOwner()
  {
    require(signers.length <= maxNumOracles, "too many oracles");
    require(signers.length == transmitters.length, "oracle length mismatch");
    require(3*f < signers.length, "faulty-oracle f too high");
    _requirePositiveF(f);
    require(keccak256(onchainConfig) == keccak256(abi.encodePacked(uint8(1) /*version*/, minAnswer, maxAnswer)), "invalid onchainConfig");

    SetConfigArgs memory args = SetConfigArgs({
      signers: signers,
      transmitters: transmitters,
      f: f,
      onchainConfig: onchainConfig,
      offchainConfigVersion: offchainConfigVersion,
      offchainConfig: offchainConfig
    });

    s_hotVars.latestEpochAndRound = 0;
    _payOracles();

    // remove any old signer/transmitter addresses
    uint256 oldLength = s_signersList.length;
    for (uint256 i = 0; i < oldLength; i++) {
      address signer = s_signersList[i];
      address transmitter = s_transmittersList[i];
      delete s_signers[signer];
      delete s_transmitters[transmitter];
    }
    delete s_signersList;
    delete s_transmittersList;

    // add new signer/transmitter addresses
    for (uint i = 0; i < args.signers.length; i++) {
      require(
        !s_signers[args.signers[i]].active,
        "repeated signer address"
      );
      s_signers[args.signers[i]] = Signer({
        active: true,
        index: uint8(i)
      });
      require(
        !s_transmitters[args.transmitters[i]].active,
        "repeated transmitter address"
      );
      s_transmitters[args.transmitters[i]] = Transmitter({
        active: true,
        index: uint8(i),
        paymentJuels: 0
      });
    }
    s_signersList = args.signers;
    s_transmittersList = args.transmitters;

    s_hotVars.f = args.f;
    uint32 previousConfigBlockNumber = s_latestConfigBlockNumber;
    s_latestConfigBlockNumber = uint32(block.number);
    s_configCount += 1;
    s_latestConfigDigest = _configDigestFromConfigData(
      block.chainid,
      address(this),
      s_configCount,
      args.signers,
      args.transmitters,
      args.f,
      args.onchainConfig,
      args.offchainConfigVersion,
      args.offchainConfig
    );

    emit ConfigSet(
      previousConfigBlockNumber,
      s_latestConfigDigest,
      s_configCount,
      args.signers,
      args.transmitters,
      args.f,
      args.onchainConfig,
      args.offchainConfigVersion,
      args.offchainConfig
    );

    uint32 latestAggregatorRoundId = s_hotVars.latestAggregatorRoundId;
    for (uint256 i = 0; i < args.signers.length; i++) {
      s_rewardFromAggregatorRoundId[i] = latestAggregatorRoundId;
    }
  }

  /// @inheritdoc OCR2Abstract
  function latestConfigDetails()
    external
    override
    view
    returns (
      uint32 configCount,
      uint32 blockNumber,
      bytes32 configDigest
    )
  {
    return (s_configCount, s_latestConfigBlockNumber, s_latestConfigDigest);
  }

  /**
   * @return list of addresses permitted to transmit reports to this contract

   * @dev The list will match the order used to specify the transmitter during setConfig
   */
  function getTransmitters()
    external
    view
    returns(address[] memory)
  {
    return s_transmittersList;
  }

  /***************************************************************************
   * Section: Onchain Validation
   **************************************************************************/

  // Configuration for validator
  struct ValidatorConfig {
    AggregatorValidatorInterface validator;
    uint32 gasLimit;
  }
  ValidatorConfig private s_validatorConfig;

  /**
   * @notice indicates that the validator configuration has been set
   * @param previousValidator previous validator contract
   * @param previousGasLimit previous gas limit for validate calls
   * @param currentValidator current validator contract
   * @param currentGasLimit current gas limit for validate calls
   */
  event ValidatorConfigSet(
    AggregatorValidatorInterface indexed previousValidator,
    uint32 previousGasLimit,
    AggregatorValidatorInterface indexed currentValidator,
    uint32 currentGasLimit
  );

  /**
   * @notice validator configuration
   * @return validator validator contract
   * @return gasLimit gas limit for validate calls
   */
  function getValidatorConfig()
    external
    view
    returns (AggregatorValidatorInterface validator, uint32 gasLimit)
  {
    ValidatorConfig memory vc = s_validatorConfig;
    return (vc.validator, vc.gasLimit);
  }

  /**
   * @notice sets validator configuration
   * @dev set newValidator to 0x0 to disable validate calls
   * @param newValidator address of the new validator contract
   * @param newGasLimit new gas limit for validate calls
   */
  function setValidatorConfig(
    AggregatorValidatorInterface newValidator,
    uint32 newGasLimit
  )
    public
    onlyOwner()
  {
    ValidatorConfig memory previous = s_validatorConfig;

    if (previous.validator != newValidator || previous.gasLimit != newGasLimit) {
      s_validatorConfig = ValidatorConfig({
        validator: newValidator,
        gasLimit: newGasLimit
      });

      emit ValidatorConfigSet(previous.validator, previous.gasLimit, newValidator, newGasLimit);
    }
  }

  function _validateAnswer(
    uint32 aggregatorRoundId,
    int256 answer
  )
    private
  {
    ValidatorConfig memory vc = s_validatorConfig;

    if (address(vc.validator) == address(0)) {
      return;
    }

    uint32 prevAggregatorRoundId = aggregatorRoundId - 1;
    int256 prevAggregatorRoundAnswer = s_transmissions[prevAggregatorRoundId].answer;
    require(
      _callWithExactGasEvenIfTargetIsNoContract(
        vc.gasLimit,
        address(vc.validator),
        abi.encodeWithSignature(
          "validate(uint256,int256,uint256,int256)",
          uint256(prevAggregatorRoundId),
          prevAggregatorRoundAnswer,
          uint256(aggregatorRoundId),
          answer
        )
      ),
      "insufficient gas"
    );
  }

  uint256 private constant CALL_WITH_EXACT_GAS_CUSHION = 5_000;

  /**
   * @dev calls target address with exactly gasAmount gas and data as calldata
   * or reverts if at least gasAmount gas is not available.
   */
  function _callWithExactGasEvenIfTargetIsNoContract(
    uint256 gasAmount,
    address target,
    bytes memory data
  )
    private
    returns (bool sufficientGas)
  {
    // solhint-disable-next-line no-inline-assembly
    assembly {
      let g := gas()
      // Compute g -= CALL_WITH_EXACT_GAS_CUSHION and check for underflow. We
      // need the cushion since the logic following the above call to gas also
      // costs gas which we cannot account for exactly. So cushion is a
      // conservative upper bound for the cost of this logic.
      if iszero(lt(g, CALL_WITH_EXACT_GAS_CUSHION)) {
        g := sub(g, CALL_WITH_EXACT_GAS_CUSHION)
        // If g - g//64 <= gasAmount, we don't have enough gas. (We subtract g//64
        // because of EIP-150.)
        if gt(sub(g, div(g, 64)), gasAmount) {
          // Call and ignore success/return data. Note that we did not check
          // whether a contract actually exists at the target address.
          pop(call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0))
          sufficientGas := true
        }
      }
    }
  }

  /***************************************************************************
   * Section: RequestNewRound
   **************************************************************************/

  AccessControllerInterface internal s_requesterAccessController;

  /**
   * @notice emitted when a new requester access controller contract is set
   * @param old the address prior to the current setting
   * @param current the address of the new access controller contract
   */
  event RequesterAccessControllerSet(AccessControllerInterface old, AccessControllerInterface current);

  /**
   * @notice emitted to immediately request a new round
   * @param requester the address of the requester
   * @param configDigest the latest transmission's configDigest
   * @param epoch the latest transmission's epoch
   * @param round the latest transmission's round
   */
  event RoundRequested(address indexed requester, bytes32 configDigest, uint32 epoch, uint8 round);

  /**
   * @notice address of the requester access controller contract
   * @return requester access controller address
   */
  function getRequesterAccessController()
    external
    view
    returns (AccessControllerInterface)
  {
    return s_requesterAccessController;
  }

  /**
   * @notice sets the requester access controller
   * @param requesterAccessController designates the address of the new requester access controller
   */
  function setRequesterAccessController(AccessControllerInterface requesterAccessController)
    public
    onlyOwner()
  {
    AccessControllerInterface oldController = s_requesterAccessController;
    if (requesterAccessController != oldController) {
      s_requesterAccessController = AccessControllerInterface(requesterAccessController);
      emit RequesterAccessControllerSet(oldController, requesterAccessController);
    }
  }

  /**
   * @notice immediately requests a new round
   * @return the aggregatorRoundId of the next round. Note: The report for this round may have been
   * transmitted (but not yet mined) *before* requestNewRound() was even called. There is *no*
   * guarantee of causality between the request and the report at aggregatorRoundId.
   */
  function requestNewRound() external returns (uint80) {
    require(msg.sender == owner() || s_requesterAccessController.hasAccess(msg.sender, msg.data),
      "Only owner&requester can call");

    uint40 latestEpochAndRound = s_hotVars.latestEpochAndRound;
    uint32 latestAggregatorRoundId = s_hotVars.latestAggregatorRoundId;

    emit RoundRequested(
      msg.sender,
      s_latestConfigDigest,
      uint32(latestEpochAndRound >> 8),
      uint8(latestEpochAndRound)
    );
    return latestAggregatorRoundId + 1;
  }

  /***************************************************************************
   * Section: Transmission
   **************************************************************************/

  /**
   * @notice indicates that a new report was transmitted
   * @param aggregatorRoundId the round to which this report was assigned
   * @param answer median of the observations attached to this report
   * @param transmitter address from which the report was transmitted
   * @param observationsTimestamp when were observations made offchain
   * @param observations observations transmitted with this report
   * @param observers i-th element is the oracle id of the oracle that made the i-th observation
   * @param juelsPerFeeCoin exchange rate between feeCoin (e.g. ETH on Ethereum) and LINK, denominated in juels
   * @param configDigest configDigest of transmission
   * @param epochAndRound least-significant byte is the OCR protocol round number, the other bytes give the big-endian OCR protocol epoch number
   */
  event NewTransmission(
    uint32 indexed aggregatorRoundId,
    int192 answer,
    address transmitter,
    uint32 observationsTimestamp,
    int192[] observations,
    bytes observers,
    int192 juelsPerFeeCoin,
    bytes32 configDigest,
    uint40 epochAndRound
  );

  // Used to relieve stack pressure in transmit
  struct Report {
    uint32 observationsTimestamp;
    bytes observers; // ith element is the index of the ith observer
    int192[] observations; // ith element is the ith observation
    int192 juelsPerFeeCoin;
  }

  // _decodeReport decodes a serialized report into a Report struct
  function _decodeReport(bytes memory rawReport)
    internal
    pure
    returns (
      Report memory
    )
  {
    uint32 observationsTimestamp;
    bytes32 rawObservers;
    int192[] memory observations;
    int192 juelsPerFeeCoin;
    (observationsTimestamp, rawObservers, observations, juelsPerFeeCoin) = abi.decode(rawReport, (uint32, bytes32, int192[], int192));

    _requireExpectedReportLength(rawReport, observations);

    uint256 numObservations = observations.length;
    bytes memory observers = abi.encodePacked(rawObservers);
    assembly {
      // we truncate observers from length 32 to the number of observations
      mstore(observers, numObservations)
    }

    return Report({
      observationsTimestamp: observationsTimestamp,
      observers: observers,
      observations: observations,
      juelsPerFeeCoin: juelsPerFeeCoin
    });
  }

  // The constant-length components of the msg.data sent to transmit.
  // See the "If we wanted to call sam" example on for example reasoning
  // https://solidity.readthedocs.io/en/v0.7.2/abi-spec.html
  uint256 private constant TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT =
    4 + // function selector
    32 * 3 + // 3 words containing reportContext
    32 + // word containing start location of abiencoded report value
    32 + // word containing start location of abiencoded rs value
    32 + // word containing start location of abiencoded ss value
    32 + // rawVs value
    32 + // word containing length of report
    32 + // word containing length rs
    32 + // word containing length of ss
    0; // placeholder

  // Make sure the calldata length matches the inputs. Otherwise, the
  // transmitter could append an arbitrarily long (up to gas-block limit)
  // string of 0 bytes, which we would reimburse at a rate of 16 gas/byte, but
  // which would only cost the transmitter 4 gas/byte.
  function _requireExpectedMsgDataLength(
    bytes calldata report,
    bytes32[] calldata rs,
    bytes32[] calldata ss
  )
    private
    pure
  {
    // calldata will never be big enough to make this overflow
    uint256 expected = TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT +
      report.length + // one byte per entry in report
      rs.length * 32 + // 32 bytes per entry in rs
      ss.length * 32 + // 32 bytes per entry in ss
      0; // placeholder
    require(msg.data.length == expected, "calldata length mismatch");
  }

  /// @inheritdoc OCR2Abstract
  function transmit(
    // reportContext consists of:
    // reportContext[0]: ConfigDigest
    // reportContext[1]: 27 byte padding, 4-byte epoch and 1-byte round
    // reportContext[2]: ExtraHash
    bytes32[3] calldata reportContext,
    bytes calldata report,
    // ECDSA signatures
    bytes32[] calldata rs,
    bytes32[] calldata ss,
    bytes32 rawVs
  )
    external
    override
  {
    // NOTE: If the arguments to this function are changed, _requireExpectedMsgDataLength and/or
    // TRANSMIT_MSGDATA_CONSTANT_LENGTH_COMPONENT need to be changed accordingly

    uint256 initialGas = gasleft(); // This line must come first

    HotVars memory hotVars = s_hotVars;

    uint40 epochAndRound = uint40(uint256(reportContext[1]));

    require(hotVars.latestEpochAndRound < epochAndRound, "stale report");

    require(s_transmitters[msg.sender].active, "unauthorized transmitter");

    require(s_latestConfigDigest == reportContext[0], "configDigest mismatch");

    _requireExpectedMsgDataLength(report, rs, ss);

    require(rs.length == hotVars.f + 1, "wrong number of signatures");
    require(rs.length == ss.length, "signatures out of registration");

    // Verify signatures attached to report
    {
      bytes32 h = keccak256(abi.encode(keccak256(report), reportContext));

      // i-th byte counts number of sigs made by i-th signer
      uint256 signedCount = 0;

      Signer memory signer;
      for (uint i = 0; i < rs.length; i++) {
        address signerAddress = ecrecover(h, uint8(rawVs[i])+27, rs[i], ss[i]);
        signer = s_signers[signerAddress];
        require(signer.active, "signature error");
        unchecked{
          signedCount += 1 << (8 * signer.index);
        }
      }

      // The first byte of the mask can be 0, because we only ever have 31 oracles
      require(signedCount & 0x0001010101010101010101010101010101010101010101010101010101010101 == signedCount, "duplicate signer");
    }

    int192 juelsPerFeeCoin = _report(hotVars, reportContext[0], epochAndRound, report);

    _payTransmitter(hotVars, juelsPerFeeCoin, uint32(initialGas), msg.sender);
  }

  /**
   * @notice details about the most recent report
   * @return configDigest domain separation tag for the latest report
   * @return epoch epoch in which the latest report was generated
   * @return round OCR round in which the latest report was generated
   * @return latestAnswer_ median value from latest report
   * @return latestTimestamp_ when the latest report was transmitted
   */
  function latestTransmissionDetails()
    external
    view
    returns (
      bytes32 configDigest,
      uint32 epoch,
      uint8 round,
      int192 latestAnswer_,
      uint64 latestTimestamp_
    )
  {
    require(msg.sender == tx.origin, "Only callable by EOA");
    return (
      s_latestConfigDigest,
      uint32(s_hotVars.latestEpochAndRound >> 8),
      uint8(s_hotVars.latestEpochAndRound),
      s_transmissions[s_hotVars.latestAggregatorRoundId].answer,
      s_transmissions[s_hotVars.latestAggregatorRoundId].transmissionTimestamp
    );
  }

  /// @inheritdoc OCR2Abstract
  function latestConfigDigestAndEpoch()
    external
    override
    view
    virtual
    returns(
      bool scanLogs,
      bytes32 configDigest,
      uint32 epoch
    )
  {
    return (false, s_latestConfigDigest, uint32(s_hotVars.latestEpochAndRound >> 8));
  }

  function _requireExpectedReportLength(
    bytes memory report,
    int192[] memory observations
  )
    private
    pure
  {
    uint256 expected =
      32 + // observationsTimestamp
      32 + // rawObservers
      32 + // observations offset
      32 + // juelsPerFeeCoin
      32 + // observations length
      32 * observations.length + // observations payload
      0;
    require(report.length == expected, "report length mismatch");
  }

  function _report(
    HotVars memory hotVars,
    bytes32 configDigest,
    uint40 epochAndRound,
    bytes memory rawReport
  )
    internal
    returns (int192 juelsPerFeeCoin)
  {
    Report memory report = _decodeReport(rawReport);


    require(report.observations.length <= maxNumOracles, "num observations out of bounds");
    // Offchain logic ensures that a quorum of oracles is operating on a matching set of at least
    // 2f+1 observations. By assumption, up to f of those can be faulty, which includes being
    // malformed. Conversely, more than f observations have to be well-formed and sent on chain.
    require(hotVars.f < report.observations.length, "too few values to trust median");

    hotVars.latestEpochAndRound = epochAndRound;

    // get median, validate its range, store it in new aggregator round
    int192 median = report.observations[report.observations.length/2];
    require(minAnswer <= median && median <= maxAnswer, "median is out of min-max range");
    hotVars.latestAggregatorRoundId++;
    s_transmissions[hotVars.latestAggregatorRoundId] =
      Transmission({
        answer: median,
        observationsTimestamp: report.observationsTimestamp,
        transmissionTimestamp: uint32(block.timestamp)
      });

    // persist updates to hotVars
    s_hotVars = hotVars;

    emit NewTransmission(
      hotVars.latestAggregatorRoundId,
      median,
      msg.sender,
      report.observationsTimestamp,
      report.observations,
      report.observers,
      report.juelsPerFeeCoin,
      configDigest,
      epochAndRound
    );
    // Emit these for backwards compatibility with offchain consumers
    // that only support legacy events
    emit NewRound(
      hotVars.latestAggregatorRoundId,
      address(0x0), // use zero address since we don't have anybody "starting" the round here
      report.observationsTimestamp
    );
    emit AnswerUpdated(
      median,
      hotVars.latestAggregatorRoundId,
      block.timestamp
    );

    _validateAnswer(hotVars.latestAggregatorRoundId, median);

    return report.juelsPerFeeCoin;
  }

  /***************************************************************************
   * Section: v2 AggregatorInterface
   **************************************************************************/

  /**
   * @notice median from the most recent report
   */
  function latestAnswer()
    public
    override
    view
    virtual
    returns (int256)
  {
    return s_transmissions[s_hotVars.latestAggregatorRoundId].answer;
  }

  /**
   * @notice timestamp of block in which last report was transmitted
   */
  function latestTimestamp()
    public
    override
    view
    virtual
    returns (uint256)
  {
    return s_transmissions[s_hotVars.latestAggregatorRoundId].transmissionTimestamp;
  }

  /**
   * @notice Aggregator round (NOT OCR round) in which last report was transmitted
   */
  function latestRound()
    public
    override
    view
    virtual
    returns (uint256)
  {
    return s_hotVars.latestAggregatorRoundId;
  }

  /**
   * @notice median of report from given aggregator round (NOT OCR round)
   * @param roundId the aggregator round of the target report
   */
  function getAnswer(uint256 roundId)
    public
    override
    view
    virtual
    returns (int256)
  {
    if (roundId > 0xFFFFFFFF) { return 0; }
    return s_transmissions[uint32(roundId)].answer;
  }

  /**
   * @notice timestamp of block in which report from given aggregator round was transmitted
   * @param roundId aggregator round (NOT OCR round) of target report
   */
  function getTimestamp(uint256 roundId)
    public
    override
    view
    virtual
    returns (uint256)
  {
    if (roundId > 0xFFFFFFFF) { return 0; }
    return s_transmissions[uint32(roundId)].transmissionTimestamp;
  }

  /***************************************************************************
   * Section: v3 AggregatorInterface
   **************************************************************************/

  /**
   * @return answers are stored in fixed-point format, with this many digits of precision
   */
  uint8 immutable public override decimals;

  /**
   * @notice aggregator contract version
   */
  uint256 constant public override version = 6;

  string internal s_description;

  /**
   * @notice human-readable description of observable this contract is reporting on
   */
  function description()
    public
    override
    view
    virtual
    returns (string memory)
  {
    return s_description;
  }

  /**
   * @notice details for the given aggregator round
   * @param roundId target aggregator round (NOT OCR round). Must fit in uint32
   * @return roundId_ roundId
   * @return answer median of report from given roundId
   * @return startedAt timestamp of when observations were made offchain
   * @return updatedAt timestamp of block in which report from given roundId was transmitted
   * @return answeredInRound roundId
   */
  function getRoundData(uint80 roundId)
    public
    override
    view
    virtual
    returns (
      uint80 roundId_,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    )
  {
    if(roundId > type(uint32).max) { return (0, 0, 0, 0, 0); }
    Transmission memory transmission = s_transmissions[uint32(roundId)];
    return (
      roundId,
      transmission.answer,
      transmission.observationsTimestamp,
      transmission.transmissionTimestamp,
      roundId
    );
  }

  /**
   * @notice aggregator details for the most recently transmitted report
   * @return roundId aggregator round of latest report (NOT OCR round)
   * @return answer median of latest report
   * @return startedAt timestamp of when observations were made offchain
   * @return updatedAt timestamp of block containing latest report
   * @return answeredInRound aggregator round of latest report
   */
  function latestRoundData()
    public
    override
    view
    virtual
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    )
  {
    uint32 latestAggregatorRoundId = s_hotVars.latestAggregatorRoundId;

    Transmission memory transmission = s_transmissions[latestAggregatorRoundId];
    return (
      latestAggregatorRoundId,
      transmission.answer,
      transmission.observationsTimestamp,
      transmission.transmissionTimestamp,
      latestAggregatorRoundId
    );
  }

  /***************************************************************************
   * Section: Configurable LINK Token
   **************************************************************************/

  // We assume that the token contract is correct. This contract is not written
  // to handle misbehaving ERC20 tokens!
  LinkTokenInterface internal s_linkToken;

  /*
   * @notice emitted when the LINK token contract is set
   * @param oldLinkToken the address of the old LINK token contract
   * @param newLinkToken the address of the new LINK token contract
   */
  event LinkTokenSet(
    LinkTokenInterface indexed oldLinkToken,
    LinkTokenInterface indexed newLinkToken
  );

  /**
   * @notice sets the LINK token contract used for paying oracles
   * @param linkToken the address of the LINK token contract
   * @param recipient remaining funds from the previous token contract are transferred
   * here
   * @dev this function will return early (without an error) without changing any state
   * if linkToken equals getLinkToken().
   * @dev this will trigger a payout so that a malicious owner cannot take from oracles
   * what is already owed to them.
   * @dev we assume that the token contract is correct. This contract is not written
   * to handle misbehaving ERC20 tokens!
   */
  function setLinkToken(
    LinkTokenInterface linkToken,
    address recipient
  ) external
    onlyOwner()
  {
    LinkTokenInterface oldLinkToken = s_linkToken;
    if (linkToken == oldLinkToken) {
      // No change, nothing to be done
      return;
    }
    // call balanceOf as a sanity check on whether we're talking to a token
    // contract
    linkToken.balanceOf(address(this));
    // we break CEI here, but that's okay because we're dealing with a correct
    // token contract (by assumption).
    _payOracles();
    uint256 remainingBalance = oldLinkToken.balanceOf(address(this));
    require(oldLinkToken.transfer(recipient, remainingBalance), "transfer remaining funds failed");
    s_linkToken = linkToken;
    emit LinkTokenSet(oldLinkToken, linkToken);
  }

  /*
   * @notice gets the LINK token contract used for paying oracles
   * @return linkToken the address of the LINK token contract
   */
  function getLinkToken()
    external
    view
    returns(LinkTokenInterface linkToken)
  {
    return s_linkToken;
  }

  /***************************************************************************
   * Section: BillingAccessController Management
   **************************************************************************/

  // Controls who can change billing parameters. A billingAdmin is not able to
  // affect any OCR protocol settings and therefore cannot tamper with the
  // liveness or integrity of a data feed. However, a billingAdmin can set
  // faulty billing parameters causing oracles to be underpaid, or causing them
  // to be paid so much that further calls to setConfig, setBilling,
  // setLinkToken will always fail due to the contract being underfunded.
  AccessControllerInterface internal s_billingAccessController;

  /**
   * @notice emitted when a new access-control contract is set
   * @param old the address prior to the current setting
   * @param current the address of the new access-control contract
   */
  event BillingAccessControllerSet(AccessControllerInterface old, AccessControllerInterface current);

  function _setBillingAccessController(AccessControllerInterface billingAccessController)
    internal
  {
    AccessControllerInterface oldController = s_billingAccessController;
    if (billingAccessController != oldController) {
      s_billingAccessController = billingAccessController;
      emit BillingAccessControllerSet(
        oldController,
        billingAccessController
      );
    }
  }

  /**
   * @notice sets billingAccessController
   * @param _billingAccessController new billingAccessController contract address
   * @dev only owner can call this
   */
  function setBillingAccessController(AccessControllerInterface _billingAccessController)
    external
    onlyOwner
  {
    _setBillingAccessController(_billingAccessController);
  }

  /**
   * @notice gets billingAccessController
   * @return address of billingAccessController contract
   */
  function getBillingAccessController()
    external
    view
    returns (AccessControllerInterface)
  {
    return s_billingAccessController;
  }

  /***************************************************************************
   * Section: Billing Configuration
   **************************************************************************/

  /**
   * @notice emitted when billing parameters are set
   * @param maximumGasPriceGwei highest gas price for which transmitter will be compensated
   * @param reasonableGasPriceGwei transmitter will receive reward for gas prices under this value
   * @param observationPaymentGjuels reward to oracle for contributing an observation to a successfully transmitted report
   * @param transmissionPaymentGjuels reward to transmitter of a successful report
   * @param accountingGas gas overhead incurred by accounting logic
   */
  event BillingSet(
    uint32 maximumGasPriceGwei,
    uint32 reasonableGasPriceGwei,
    uint32 observationPaymentGjuels,
    uint32 transmissionPaymentGjuels,
    uint24 accountingGas
  );

  /**
   * @notice sets billing parameters
   * @param maximumGasPriceGwei highest gas price for which transmitter will be compensated
   * @param reasonableGasPriceGwei transmitter will receive reward for gas prices under this value
   * @param observationPaymentGjuels reward to oracle for contributing an observation to a successfully transmitted report
   * @param transmissionPaymentGjuels reward to transmitter of a successful report
   * @param accountingGas gas overhead incurred by accounting logic
   * @dev access control provided by billingAccessController
   */
  function setBilling(
    uint32 maximumGasPriceGwei,
    uint32 reasonableGasPriceGwei,
    uint32 observationPaymentGjuels,
    uint32 transmissionPaymentGjuels,
    uint24 accountingGas
  )
    external
  {
    AccessControllerInterface access = s_billingAccessController;
    require(msg.sender == owner() || access.hasAccess(msg.sender, msg.data),
      "Only owner&billingAdmin can call");
    _payOracles();

    s_hotVars.maximumGasPriceGwei = maximumGasPriceGwei;
    s_hotVars.reasonableGasPriceGwei = reasonableGasPriceGwei;
    s_hotVars.observationPaymentGjuels = observationPaymentGjuels;
    s_hotVars.transmissionPaymentGjuels = transmissionPaymentGjuels;
    s_hotVars.accountingGas = accountingGas;

    emit BillingSet(maximumGasPriceGwei, reasonableGasPriceGwei,
      observationPaymentGjuels, transmissionPaymentGjuels, accountingGas);
  }

  /**
   * @notice gets billing parameters
   * @param maximumGasPriceGwei highest gas price for which transmitter will be compensated
   * @param reasonableGasPriceGwei transmitter will receive reward for gas prices under this value
   * @param observationPaymentGjuels reward to oracle for contributing an observation to a successfully transmitted report
   * @param transmissionPaymentGjuels reward to transmitter of a successful report
   * @param accountingGas gas overhead of the accounting logic
   */
  function getBilling()
    external
    view
    returns (
      uint32 maximumGasPriceGwei,
      uint32 reasonableGasPriceGwei,
      uint32 observationPaymentGjuels,
      uint32 transmissionPaymentGjuels,
      uint24 accountingGas
    )
  {
    return (
      s_hotVars.maximumGasPriceGwei,
      s_hotVars.reasonableGasPriceGwei,
      s_hotVars.observationPaymentGjuels,
      s_hotVars.transmissionPaymentGjuels,
      s_hotVars.accountingGas
    );
  }

  /***************************************************************************
   * Section: Payments and Withdrawals
   **************************************************************************/

  /**
   * @notice withdraws an oracle's payment from the contract
   * @param transmitter the transmitter address of the oracle
   * @dev must be called by oracle's payee address
   */
  function withdrawPayment(address transmitter)
    external
  {
    require(msg.sender == s_payees[transmitter], "Only payee can withdraw");
    _payOracle(transmitter);
  }

  /**
   * @notice query an oracle's payment amount, denominated in juels
   * @param transmitterAddress the transmitter address of the oracle
   */
  function owedPayment(address transmitterAddress)
    public
    view
    returns (uint256)
  {
    Transmitter memory transmitter = s_transmitters[transmitterAddress];
    if (!transmitter.active) { return 0; }
    // safe from overflow:
    // s_hotVars.latestAggregatorRoundId - s_rewardFromAggregatorRoundId[transmitter.index] <= 2**32
    // s_hotVars.observationPaymentGjuels <= 2**32
    // 1 gwei <= 2**32
    // hence juelsAmount <= 2**96
    uint256 juelsAmount =
      uint256(s_hotVars.latestAggregatorRoundId - s_rewardFromAggregatorRoundId[transmitter.index]) *
      uint256(s_hotVars.observationPaymentGjuels) *
      (1 gwei);
    juelsAmount += transmitter.paymentJuels;
    return juelsAmount;
  }

  /**
   * @notice emitted when an oracle has been paid LINK
   * @param transmitter address from which the oracle sends reports to the transmit method
   * @param payee address to which the payment is sent
   * @param amount amount of LINK sent
   * @param linkToken address of the LINK token contract
   */
  event OraclePaid(
    address indexed transmitter,
    address indexed payee,
    uint256 amount,
    LinkTokenInterface indexed linkToken
  );

  // _payOracle pays out transmitter's balance to the corresponding payee, and zeros it out
  function _payOracle(address transmitterAddress)
    internal
  {
    Transmitter memory transmitter = s_transmitters[transmitterAddress];
    if (!transmitter.active) { return; }
    uint256 juelsAmount = owedPayment(transmitterAddress);
    if (juelsAmount > 0) {
      address payee = s_payees[transmitterAddress];
      // Poses no re-entrancy issues, because LINK.transfer does not yield
      // control flow.
      require(s_linkToken.transfer(payee, juelsAmount), "insufficient funds");
      s_rewardFromAggregatorRoundId[transmitter.index] = s_hotVars.latestAggregatorRoundId;
      s_transmitters[transmitterAddress].paymentJuels = 0;
      emit OraclePaid(transmitterAddress, payee, juelsAmount, s_linkToken);
    }
  }

  // _payOracles pays out all transmitters, and zeros out their balances.
  //
  // It's much more gas-efficient to do this as a single operation, to avoid
  // hitting storage too much.
  function _payOracles()
    internal
  {
    unchecked {
      LinkTokenInterface linkToken = s_linkToken;
      uint32 latestAggregatorRoundId = s_hotVars.latestAggregatorRoundId;
      uint32[maxNumOracles] memory rewardFromAggregatorRoundId = s_rewardFromAggregatorRoundId;
      address[] memory transmitters = s_transmittersList;
      for (uint transmitteridx = 0; transmitteridx < transmitters.length; transmitteridx++) {
        uint256 reimbursementAmountJuels = s_transmitters[transmitters[transmitteridx]].paymentJuels;
        s_transmitters[transmitters[transmitteridx]].paymentJuels = 0;
        uint256 obsCount = latestAggregatorRoundId - rewardFromAggregatorRoundId[transmitteridx];
        uint256 juelsAmount =
          obsCount * uint256(s_hotVars.observationPaymentGjuels) * (1 gwei) + reimbursementAmountJuels;
        if (juelsAmount > 0) {
            address payee = s_payees[transmitters[transmitteridx]];
            // Poses no re-entrancy issues, because LINK.transfer does not yield
            // control flow.
            require(linkToken.transfer(payee, juelsAmount), "insufficient funds");
            rewardFromAggregatorRoundId[transmitteridx] = latestAggregatorRoundId;
            emit OraclePaid(transmitters[transmitteridx], payee, juelsAmount, linkToken);
          }
      }
      // "Zero" the accounting storage variables
      s_rewardFromAggregatorRoundId = rewardFromAggregatorRoundId;
    }
  }

  /**
   * @notice withdraw any available funds left in the contract, up to amount, after accounting for the funds due to participants in past reports
   * @param recipient address to send funds to
   * @param amount maximum amount to withdraw, denominated in LINK-wei.
   * @dev access control provided by billingAccessController
   */
  function withdrawFunds(
    address recipient,
    uint256 amount
  )
    external
  {
    require(msg.sender == owner() || s_billingAccessController.hasAccess(msg.sender, msg.data),
      "Only owner&billingAdmin can call");
    uint256 linkDue = _totalLinkDue();
    uint256 linkBalance = s_linkToken.balanceOf(address(this));
    require(linkBalance >= linkDue, "insufficient balance");
    require(s_linkToken.transfer(recipient, _min(linkBalance - linkDue, amount)), "insufficient funds");
  }

  // Total LINK due to participants in past reports (denominated in Juels).
  function _totalLinkDue()
    internal
    view
    returns (uint256 linkDue)
  {
    // Argument for overflow safety: We do all computations in
    // uint256s. The inputs to linkDue are:
    // - the <= 31 observation rewards each of which has less than
    //   64 bits (32 bits for observationPaymentGjuels, 32 bits
    //   for wei/gwei conversion). Hence 69 bits are sufficient for this part.
    // - the <= 31 gas reimbursements, each of which consists of at most 96
    //   bits. Hence 101 bits are sufficient for this part.
    // So we never need more than 102 bits.

    address[] memory transmitters = s_transmittersList;
    uint256 n = transmitters.length;

    uint32 latestAggregatorRoundId = s_hotVars.latestAggregatorRoundId;
    uint32[maxNumOracles] memory rewardFromAggregatorRoundId = s_rewardFromAggregatorRoundId;
    for (uint i = 0; i < n; i++) {
      linkDue += latestAggregatorRoundId - rewardFromAggregatorRoundId[i];
    }
    // Convert observationPaymentGjuels to uint256, or this overflows!
    linkDue *= uint256(s_hotVars.observationPaymentGjuels) * (1 gwei);
    for (uint i = 0; i < n; i++) {
      linkDue += uint256(s_transmitters[transmitters[i]].paymentJuels);
    }
  }

  /**
   * @notice allows oracles to check that sufficient LINK balance is available
   * @return availableBalance LINK available on this contract, after accounting for outstanding obligations. can become negative
   */
  function linkAvailableForPayment()
    external
    view
    returns (int256 availableBalance)
  {
    // there are at most one billion LINK, so this cast is safe
    int256 balance = int256(s_linkToken.balanceOf(address(this)));
    // according to the argument in the definition of _totalLinkDue,
    // _totalLinkDue is never greater than 2**102, so this cast is safe
    int256 due = int256(_totalLinkDue());
    // safe from overflow according to above sizes
    return int256(balance) - int256(due);
  }

  /**
   * @notice number of observations oracle is due to be reimbursed for
   * @param transmitterAddress address used by oracle for signing or transmitting reports
   */
  function oracleObservationCount(address transmitterAddress)
    external
    view
    returns (uint32)
  {
    Transmitter memory transmitter = s_transmitters[transmitterAddress];
    if (!transmitter.active) { return 0; }
    return s_hotVars.latestAggregatorRoundId - s_rewardFromAggregatorRoundId[transmitter.index];
  }

  /***************************************************************************
   * Section: Transmitter Payment
   **************************************************************************/

  // Gas price at which the transmitter should be reimbursed, in gwei/gas
  function _reimbursementGasPriceGwei(
    uint256 txGasPriceGwei,
    uint256 reasonableGasPriceGwei,
    uint256 maximumGasPriceGwei
  )
    internal
    pure
    returns (uint256)
  {
    // this happens on the path for transmissions. we'd rather pay out
    // a wrong reward than risk a liveness failure due to a revert.
    unchecked {
      // Reward the transmitter for choosing an efficient gas price: if they manage
      // to come in lower than considered reasonable, give them half the savings.
      uint256 gasPriceGwei = txGasPriceGwei;
      if (txGasPriceGwei < reasonableGasPriceGwei) {
        // Give transmitter half the savings for coming in under the reasonable gas price
        gasPriceGwei += (reasonableGasPriceGwei - txGasPriceGwei) / 2;
      }
      // Don't reimburse a gas price higher than maximumGasPriceGwei
      return _min(gasPriceGwei, maximumGasPriceGwei);
    }
  }

  // gas reimbursement due the transmitter, in wei
  function _transmitterGasCostWei(
    uint256 initialGas,
    uint256 gasPriceGwei,
    uint256 callDataGas,
    uint256 accountingGas,
    uint256 leftGas
  )
    internal
    pure
    returns (uint256)
  {
    // this happens on the path for transmissions. we'd rather pay out
    // a wrong reward than risk a liveness failure due to a revert.
    unchecked {
      require(initialGas >= leftGas, "leftGas cannot exceed initialGas");
      uint256 usedGas =
        initialGas - leftGas + // observed gas usage
        callDataGas + accountingGas; // estimated gas usage
      uint256 fullGasCostWei = usedGas * gasPriceGwei * (1 gwei);
      return fullGasCostWei;
    }
  }

  function _payTransmitter(
    HotVars memory hotVars,
    int192 juelsPerFeeCoin,
    uint32 initialGas,
    address transmitter
  )
    internal
    virtual
  {
    // this happens on the path for transmissions. we'd rather pay out
    // a wrong reward than risk a liveness failure due to a revert.
    unchecked {
      // we can't deal with negative juelsPerFeeCoin, better to just not pay
      if (juelsPerFeeCoin < 0) {
        return;
      }...

// [truncated — 56053 bytes total]
OwnerIsCreator.sol 20 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./ConfirmedOwner.sol";

/**
 * @title The OwnerIsCreator contract
 * @notice A contract with helpers for basic contract ownership.
 */
contract OwnerIsCreator is ConfirmedOwner {

  constructor(
  )
    ConfirmedOwner(
      msg.sender
    )
  {
  }

}
ConfirmedOwnerWithProposal.sol 113 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./interfaces/OwnableInterface.sol";

/**
 * @title The ConfirmedOwner contract
 * @notice A contract with helpers for basic contract ownership.
 */
contract ConfirmedOwnerWithProposal is OwnableInterface {

  address private s_owner;
  address private s_pendingOwner;

  event OwnershipTransferRequested(
    address indexed from,
    address indexed to
  );
  event OwnershipTransferred(
    address indexed from,
    address indexed to
  );

  constructor(
    address newOwner,
    address pendingOwner
  ) {
    require(newOwner != address(0), "Cannot set owner to zero");

    s_owner = newOwner;
    if (pendingOwner != address(0)) {
      _transferOwnership(pendingOwner);
    }
  }

  /**
   * @notice Allows an owner to begin transferring ownership to a new address,
   * pending.
   */
  function transferOwnership(
    address to
  )
    public
    override
    onlyOwner()
  {
    _transferOwnership(to);
  }

  /**
   * @notice Allows an ownership transfer to be completed by the recipient.
   */
  function acceptOwnership()
    external
    override
  {
    require(msg.sender == s_pendingOwner, "Must be proposed owner");

    address oldOwner = s_owner;
    s_owner = msg.sender;
    s_pendingOwner = address(0);

    emit OwnershipTransferred(oldOwner, msg.sender);
  }

  /**
   * @notice Get the current owner
   */
  function owner()
    public
    view
    override
    returns (
      address
    )
  {
    return s_owner;
  }

  /**
   * @notice validate, transfer ownership, and emit relevant events
   */
  function _transferOwnership(
    address to
  )
    private
  {
    require(to != msg.sender, "Cannot transfer to self");

    s_pendingOwner = to;

    emit OwnershipTransferRequested(s_owner, to);
  }

  /**
   * @notice validate access
   */
  function _validateOwnership()
    internal
    view
  {
    require(msg.sender == s_owner, "Only callable by owner");
  }

  /**
   * @notice Reverts if called by anyone other than the contract owner.
   */
  modifier onlyOwner() {
    _validateOwnership();
    _;
  }

}
SimpleReadAccessController.sol 36 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./SimpleWriteAccessController.sol";

/**
 * @title SimpleReadAccessController
 * @notice Gives access to:
 * - any externally owned account (note that offchain actors can always read
 * any contract storage regardless of onchain access control measures, so this
 * does not weaken the access control while improving usability)
 * - accounts explicitly added to an access list
 * @dev SimpleReadAccessController is not suitable for access controlling writes
 * since it grants any externally owned account access! See
 * SimpleWriteAccessController for that.
 */
contract SimpleReadAccessController is SimpleWriteAccessController {

  /**
   * @notice Returns the access of an address
   * @param _user The address to query
   */
  function hasAccess(
    address _user,
    bytes memory _calldata
  )
    public
    view
    virtual
    override
    returns (bool)
  {
    return super.hasAccess(_user, _calldata) || _user == tx.origin;
  }

}
SimpleWriteAccessController.sol 114 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./OwnerIsCreator.sol";
import "./interfaces/AccessControllerInterface.sol";

/**
 * @title SimpleWriteAccessController
 * @notice Gives access to accounts explicitly added to an access list by the
 * controller's owner.
 * @dev does not make any special permissions for externally, see
 * SimpleReadAccessController for that.
 */
contract SimpleWriteAccessController is AccessControllerInterface, OwnerIsCreator {

  bool public checkEnabled;
  mapping(address => bool) internal accessList;

  event AddedAccess(address user);
  event RemovedAccess(address user);
  event CheckAccessEnabled();
  event CheckAccessDisabled();

  constructor()
  // TODO
  // this is modified from the version in the Chainlink monorepo
  //  OwnerIsCreator()
  {
    checkEnabled = true;
  }

  /**
   * @notice Returns the access of an address
   * @param _user The address to query
   */
  function hasAccess(
    address _user,
    bytes memory
  )
    public
    view
    virtual
    override
    returns (bool)
  {
    return accessList[_user] || !checkEnabled;
  }

  /**
   * @notice Adds an address to the access list
   * @param _user The address to add
   */
  function addAccess(address _user)
    external
    onlyOwner()
  {
    if (!accessList[_user]) {
      accessList[_user] = true;

      emit AddedAccess(_user);
    }
  }

  /**
   * @notice Removes an address from the access list
   * @param _user The address to remove
   */
  function removeAccess(address _user)
    external
    onlyOwner()
  {
    if (accessList[_user]) {
      accessList[_user] = false;

      emit RemovedAccess(_user);
    }
  }

  /**
   * @notice makes the access check enforced
   */
  function enableAccessCheck()
    external
    onlyOwner()
  {
    if (!checkEnabled) {
      checkEnabled = true;

      emit CheckAccessEnabled();
    }
  }

  /**
   * @notice makes the access check unenforced
   */
  function disableAccessCheck()
    external
    onlyOwner()
  {
    if (checkEnabled) {
      checkEnabled = false;

      emit CheckAccessDisabled();
    }
  }

  /**
   * @dev reverts if the caller does not have access
   */
  modifier checkAccess() {
    require(hasAccess(msg.sender, msg.data), "No access");
    _;
  }
}
OwnableInterface.sol 18 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface OwnableInterface {
  function owner()
    external
    returns (
      address
    );

  function transferOwnership(
    address recipient
  )
    external;

  function acceptOwnership()
    external;
}
LinkTokenInterface.sol 17 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface LinkTokenInterface {
  function allowance(address owner, address spender) external view returns (uint256 remaining);
  function approve(address spender, uint256 value) external returns (bool success);
  function balanceOf(address owner) external view returns (uint256 balance);
  function decimals() external view returns (uint8 decimalPlaces);
  function decreaseApproval(address spender, uint256 addedValue) external returns (bool success);
  function increaseApproval(address spender, uint256 subtractedValue) external;
  function name() external view returns (string memory tokenName);
  function symbol() external view returns (string memory tokenSymbol);
  function totalSupply() external view returns (uint256 totalTokensIssued);
  function transfer(address to, uint256 value) external returns (bool success);
  function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool success);
  function transferFrom(address from, address to, uint256 value) external returns (bool success);
}
AccessControlledOCR2Aggregator.sol 155 lines
// SPDX-License-Identifier: MIT
pragma solidity =0.8.19;

import "./OCR2Aggregator.sol";
import "./SimpleReadAccessController.sol";

/**
 * @notice Wrapper of OCR2Aggregator which checks read access on Aggregator-interface methods
 */
contract AccessControlledOCR2Aggregator is OCR2Aggregator, SimpleReadAccessController {

  constructor(
    LinkTokenInterface _link,
    int192 _minAnswer,
    int192 _maxAnswer,
    AccessControllerInterface _billingAccessController,
    AccessControllerInterface _requesterAccessController,
    uint8 _decimals,
    string memory description
  )
    OCR2Aggregator(
      _link,
      _minAnswer,
      _maxAnswer,
      _billingAccessController,
      _requesterAccessController,
      _decimals,
      description
    ) {
    }

  /*
   * Versioning
   */

  function typeAndVersion()
    external
    override
    pure
    virtual
    returns (string memory)
  {
    return "AccessControlledOCR2Aggregator 1.0.0";
  }


  /*
   * v2 Aggregator interface
   */

  /// @inheritdoc OCR2Aggregator
  function latestAnswer()
    public
    override
    view
    checkAccess()
    returns (int256)
  {
    return super.latestAnswer();
  }

  /// @inheritdoc OCR2Aggregator
  function latestTimestamp()
    public
    override
    view
    checkAccess()
    returns (uint256)
  {
    return super.latestTimestamp();
  }

  /// @inheritdoc OCR2Aggregator
  function latestRound()
    public
    override
    view
    checkAccess()
    returns (uint256)
  {
    return super.latestRound();
  }

  /// @inheritdoc OCR2Aggregator
  function getAnswer(uint256 _roundId)
    public
    override
    view
    checkAccess()
    returns (int256)
  {
    return super.getAnswer(_roundId);
  }

  /// @inheritdoc OCR2Aggregator
  function getTimestamp(uint256 _roundId)
    public
    override
    view
    checkAccess()
    returns (uint256)
  {
    return super.getTimestamp(_roundId);
  }

  /*
   * v3 Aggregator interface
   */

  /// @inheritdoc OCR2Aggregator
  function description()
    public
    override
    view
    checkAccess()
    returns (string memory)
  {
    return super.description();
  }

  /// @inheritdoc OCR2Aggregator
  function getRoundData(uint80 _roundId)
    public
    override
    view
    checkAccess()
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    )
  {
    return super.getRoundData(_roundId);
  }

  /// @inheritdoc OCR2Aggregator
  function latestRoundData()
    public
    override
    view
    checkAccess()
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    )
  {
    return super.latestRoundData();
  }

}
AggregatorInterface.sol 13 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface AggregatorInterface {
  function latestAnswer() external view returns (int256);
  function latestTimestamp() external view returns (uint256);
  function latestRound() external view returns (uint256);
  function getAnswer(uint256 roundId) external view returns (int256);
  function getTimestamp(uint256 roundId) external view returns (uint256);

  event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt);
  event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt);
}
AggregatorV3Interface.sol 31 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface AggregatorV3Interface {

  function decimals() external view returns (uint8);
  function description() external view returns (string memory);
  function version() external view returns (uint256);

  function getRoundData(uint80 _roundId)
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );
  function latestRoundData()
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );

}
AggregatorV2V3Interface.sol 9 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./AggregatorInterface.sol";
import "./AggregatorV3Interface.sol";

interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface
{
}
TypeAndVersionInterface.sol 9 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface TypeAndVersionInterface{
  function typeAndVersion()
    external
    pure
    returns (string memory);
}
AccessControllerInterface.sol 6 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface AccessControllerInterface {
  function hasAccess(address user, bytes calldata data) external view returns (bool);
}
AggregatorValidatorInterface.sol 11 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface AggregatorValidatorInterface {
  function validate(
    uint256 previousRoundId,
    int256 previousAnswer,
    uint256 currentRoundId,
    int256 currentAnswer
  ) external returns (bool);
}
OCRConfigurationStoreEVMSimple.sol 63 lines
// SPDX-License-Identifier: MIT
pragma solidity =0.8.19;

import "./interfaces/TypeAndVersionInterface.sol";
import "./lib/ConfigDigestUtilEVMSimple.sol";
import "./OwnerIsCreator.sol";
import "./OCR2Abstract.sol";

/// @title OCRConfigurationStoreEVMSimple
/// @notice This contract stores configurations for protocol versions OCR2 and
/// above in contract storage. It uses the "EVMSimple" config digester.
contract OCRConfigurationStoreEVMSimple is TypeAndVersionInterface {

    struct ConfigurationEVMSimple {
        address[] signers;
        address[] transmitters;
        bytes onchainConfig;
        bytes offchainConfig;
        address contractAddress;
        uint64 offchainConfigVersion;
        uint32 configCount;
        uint8 f;
    }

    /// @notice a list of configurations keyed by their digest
    mapping(bytes32 => ConfigurationEVMSimple) internal s_configurations;

    /// @notice emitted when a new configuration is added
    event NewConfiguration(bytes32 indexed configDigest);

    /// @notice adds a new configuration to the store
    function addConfig(ConfigurationEVMSimple calldata configuration) external returns (bytes32) {

        bytes32 configDigest = ConfigDigestUtilEVMSimple.configDigestFromConfigData(
            block.chainid,
            configuration.contractAddress,
            configuration.configCount,
            configuration.signers,
            configuration.transmitters,
            configuration.f,
            configuration.onchainConfig,
            configuration.offchainConfigVersion,
            configuration.offchainConfig
        );

        s_configurations[configDigest] = configuration;

        emit NewConfiguration(configDigest);

        return configDigest;
    }

    /// @notice reads a configuration from the store
    function readConfig(bytes32 configDigest) external view returns (ConfigurationEVMSimple memory) {
        return s_configurations[configDigest];
    }

    /// @inheritdoc TypeAndVersionInterface
    function typeAndVersion() external override pure virtual returns (string memory)
    {
        return "OCRConfigurationStoreEVMSimple 1.0.0";
    }
}
ConfigDigestUtilEVMSimple.sol 42 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;


/// @title ConfigDigestUtilEVMSimple
/// @notice ConfigDigest related utility functions for "EVMSimple" config
/// digester
library ConfigDigestUtilEVMSimple {

    function configDigestFromConfigData(
        uint256 chainId,
        address contractAddress,
        uint64 configCount,
        address[] memory signers,
        address[] memory transmitters,
        uint8 f,
        bytes memory onchainConfig,
        uint64 offchainConfigVersion,
        bytes memory offchainConfig
    ) internal pure returns (bytes32)
    {
        uint256 hash = uint256(
            keccak256(
                abi.encode(
                    chainId,
                    contractAddress,
                    configCount,
                    signers,
                    transmitters,
                    f,
                    onchainConfig,
                    offchainConfigVersion,
                    offchainConfig
        )));

        uint256 prefixMask = type(uint256).max << (256-16); // 0xFFFF00..00
        uint256 prefix = 0x0001 << (256-16); // 0x000100..00

        return bytes32((prefix & prefixMask) | (hash & ~prefixMask));
    }

}

Read Contract

checkEnabled 0xdc7f0124 → bool
decimals 0x313ce567 → uint8
description 0x7284e416 → string
getAnswer 0xb5ab58dc → int256
getBilling 0x29937268 → uint32, uint32, uint32, uint32, uint24
getBillingAccessController 0xc4c92b37 → address
getLinkToken 0xe76d5168 → address
getRequesterAccessController 0xdaffc4b5 → address
getRoundData 0x9a6fc8f5 → uint80, int256, uint256, uint256, uint80
getTimestamp 0xb633620c → uint256
getTransmitters 0x666cab8d → address[]
getValidatorConfig 0x9bd2c0b1 → address, uint32
hasAccess 0x6b14daf8 → bool
latestAnswer 0x50d25bcd → int256
latestConfigDetails 0x81ff7048 → uint32, uint32, bytes32
latestConfigDigestAndEpoch 0xafcb95d7 → bool, bytes32, uint32
latestRound 0x668a0f02 → uint256
latestRoundData 0xfeaf968c → uint80, int256, uint256, uint256, uint80
latestTimestamp 0x8205bf6a → uint256
latestTransmissionDetails 0xe5fe4577 → bytes32, uint32, uint8, int192, uint64
linkAvailableForPayment 0xd09dc339 → int256
maxAnswer 0x70da2f67 → int192
minAnswer 0x22adbc78 → int192
oracleObservationCount 0xe4902f82 → uint32
owedPayment 0x0eafb25b → uint256
owner 0x8da5cb5b → address
typeAndVersion 0x181f5a77 → string
version 0x54fd4d50 → uint256

Write Contract 19 functions

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

acceptOwnership 0x79ba5097
No parameters
acceptPayeeship 0xb121e147
address transmitter
addAccess 0xa118f249
address _user
disableAccessCheck 0x0a756983
No parameters
enableAccessCheck 0x8038e4a1
No parameters
removeAccess 0x8823da6c
address _user
requestNewRound 0x98e5b12a
No parameters
returns: uint80
setBilling 0x643dc105
uint32 maximumGasPriceGwei
uint32 reasonableGasPriceGwei
uint32 observationPaymentGjuels
uint32 transmissionPaymentGjuels
uint24 accountingGas
setBillingAccessController 0xfbffd2c1
address _billingAccessController
setConfig 0xe3d0e712
address[] signers
address[] transmitters
uint8 f
bytes onchainConfig
uint64 offchainConfigVersion
bytes offchainConfig
setLinkToken 0x4fb17470
address linkToken
address recipient
setPayees 0x9c849b30
address[] transmitters
address[] payees
setRequesterAccessController 0x9e3ceeab
address requesterAccessController
setValidatorConfig 0xeb457163
address newValidator
uint32 newGasLimit
transferOwnership 0xf2fde38b
address to
transferPayeeship 0xeb5dcd6c
address transmitter
address proposed
transmit 0xb1dc65a4
bytes32[3] reportContext
bytes report
bytes32[] rs
bytes32[] ss
bytes32 rawVs
withdrawFunds 0xc1075329
address recipient
uint256 amount
withdrawPayment 0x8ac28d5a
address transmitter

Recent Transactions

No transactions found for this address